drc-3.2.2/0000755000076400001450000000000013163367152011260 5ustar denisitadmdrc-3.2.2/source/0000755000076400001450000000000013165107362012555 5ustar denisitadmdrc-3.2.2/source/drc.workspace0000644000076400001450000000041612033305710015234 0ustar denisitadm drc-3.2.2/source/fftsg.h0000644000076400001450000000172711320611736014042 0ustar denisitadm/* Fast Fourier/Cosine/Sine Transform Copyright Takuya OOURA, 1996-2001 (Email: ooura@kurims.kyoto-u.ac.jp or ooura@mmm.t.u-tokyo.ac.jp) You may use, copy, modify and distribute this code for any purpose (include commercial use) and without fee. http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html */ #ifndef fftsg_h #define fftsg_h #include "drc.h" #ifdef __cplusplus extern "C" { #endif #define OouraForward (-1) #define OouraBackward (1) #define OouraRForward (1) #define OouraRBackward (-1) void cdft(int nx2, int dir, DRCFloat * data, int * ip, DRCFloat * w); void rdft(int n, int dir, DRCFloat * data, int * ip, DRCFloat * w); void ddct(int n, int dir, DRCFloat * data, int * ip, DRCFloat * w); void ddst(int n, int dir, DRCFloat * data, int * ip, DRCFloat * w); void dfct(int n, DRCFloat *a, DRCFloat *t, int *ip, DRCFloat *w); void dfst(int n, DRCFloat *a, DRCFloat *t, int *ip, DRCFloat *w); #ifdef __cplusplus } #endif #endif drc-3.2.2/source/baselib.h0000644000076400001450000000705513162156312014332 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Funzioni di libreria base */ #ifndef BaseLib_h #define BaseLib_h /* Inclusioni */ #include "dsplib.h" #include "boolean.h" #include "drc.h" #include /* Output stringhe con sync output e parametro */ int sputsp(const char * s, const char * p); /* Output stringhe con sync output */ int sputs(const char * s); /* Determina la lunghezza di un file */ size_t FSize(FILE * F); /* Tipo file da leggere */ typedef enum { PcmInt16Bit = 'I', PcmFloat32Bit = 'F', PcmFloat64Bit = 'D' } IFileType; /* Tipo ampiezza target function */ typedef enum { MAGLinear = 'L', MAGdB = 'D' } TFMagType; /* Legge parte di un file di ingresso e lo pone nell'array indicato di dimensione InitWindow. Ritorna true se l'operazione ha successo. */ Boolean ReadSignal(const char * FName,DRCFloat * Dst,const int InitWindow, const int ImpulseCenter,const IFileType FType, int * PreSpikeStart, int * PostSpikeEnd); /* Scrive il segnale indicato su disco */ Boolean WriteSignal(const char * FName,const DRCFloat * Src,const int SSize, const IFileType FType); /* Sovrascrive il segnale indicato su disco */ Boolean OverwriteSignal(const char * FName,const DRCFloat * Src,const int SSize, const int Skip, const IFileType FType); /* Calcola l'autocorrelazione del sgnale S */ Boolean AutoCorrelation(DLReal * S, int N); /* Calcola la cross correlazione tra S1 e S2 */ /* XC deve avere lunghezza 2N - 1 */ Boolean CrossCorrelation(DLReal * S1, DLReal * S2, int N, DLReal * XC); /* Calcola il ritardo di gruppo del segnale S */ Boolean GroupDelay(const DLReal * S, const int N, DLReal * GD); /* I/O Delay computation, reliable only for simple impulse responses */ DLReal LinearDelay(DLReal * Hn,unsigned int N,unsigned int Np,DLReal MZE); /* Conta il numero di righe in un file */ int FLineCount(const char * FName); /* Legge i punti di generazione filtro FIR dal file indicato */ Boolean ReadPoints(char * CorrFile,const TFMagType MagType, DLReal * FilterFreqs,DLReal * FilterM,DLReal * FilterP,const int NPoints, int SampleRate); /* Integra due funzioni di trsferimento definite per punti, usando una interpolazione lineare, ritorna il numero di punti generati, che non sono mai pi di NPoints1 + NPoints2 */ int LITFMerge(DLReal * FilterFreqs1,DLComplex * FilterPoints1,const int NPoints1, DLReal * FilterFreqs2,DLComplex * FilterPoints2,const int NPoints2, DLReal * FilterFreqsOut,DLComplex * FilterPointsOut); /* Trova il valore massimo all'interno di un file. */ int FindMaxPcm(const char * FName,const IFileType FType); #endif drc-3.2.2/source/drc.workspace.layout0000644000076400001450000000035313165107243016560 0ustar denisitadm drc-3.2.2/source/dsplib.h0000644000076400001450000000355713162156312014211 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : DspLib.h Autore : Sbragion Denis Descrizione : Definizioni base Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #ifndef DspLib_h #define DspLib_h #include #include #include "boolean.h" #include "drc.h" typedef DRCFloat DLReal; /* Imposta la funzioni trigonometriche ridotte */ #define DLSin DRCSin #define DLCos DRCCos #ifndef M_PI #define M_PI ((DLReal) 3.14159265358979323846264338327950288) #endif #ifndef M_2PI #define M_2PI ((DLReal) 6.28318530717958647692528676655900576) #endif typedef std::complex DLComplex; #endif /***************************************************************************/ drc-3.2.2/source/hd.cpp0000644000076400001450000002421613162156312013655 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Deconvoluzione omomorfa */ /* Inclusioni */ #include "hd.h" #include "fft.h" #include "baselib.h" #include "level.h" #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Effettua la deconvoluzione omomorfa del segnale In */ /* Versione basata sul calcolo del Cepstrum */ Boolean CepstrumHD(const DLReal * In, DLReal * MPOut, DLReal * EPOut, const int N, const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; int FS; int I; Boolean LogLimit; DLReal CV; /* Controlla se si deve adottare una potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for (FS = 1;FS <= N;FS <<= 1); FS *= 1 << MExp; } else FS = N; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < N;I++) FFTArray1[I] = In[I]; /* Azzera la parte rimanente */ for (I = N;I < FS;I++) FFTArray1[I] = 0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Calcola i valori per il cepstrum */ LogLimit = False; for (I = 0;I < FS;I++) { CV = std::abs(FFTArray1[I]); if (CV <= 0) { LogLimit = True; FFTArray2[I] = (DLReal) log(DRCMinFloat); } else FFTArray2[I] = std::log(CV); } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: log limit reached in cepstrum computation."); /* Calcola il cepstrum */ IFft(FFTArray2,FS); /* Finestra il cepstrum */ for (I = 1; I < FS/2;I++) FFTArray2[I] *= 2; for (I = FS/2 + 1; I < FS;I++) FFTArray2[I] = 0; /* Calcola la trsformata del cepstrum finestrato */ Fft(FFTArray2,FS); /* Effettua il calcolo dell'esponenziale */ for (I = 0;I < FS;I++) FFTArray2[I] = std::exp(FFTArray2[I]); /* Verifica se deve estrarre la componente EP */ if (EPOut != NULL) { /* Determina la trasformata della parte excess phase */ for (I = 0;I < FS;I++) FFTArray1[I] = std::polar((DLReal) 1.0, std::arg(FFTArray1[I]) - std::arg(FFTArray2[I])); /* Determina la risposta del sistema excess phase */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < N;I++) EPOut[I] = std::real(FFTArray1[I]); } /* Verifica se deve estrarre la componente MP */ if (MPOut != NULL) { /* Determina la risposta del sistema a fase minima */ IFft(FFTArray2,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < N;I++) MPOut[I] = std::real(FFTArray2[I]); } /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } /* Effettua la deconvoluzione omomorfa del segnale In */ /* Versione basata sulla trasformata di Hilbert */ Boolean HilbertHD(const DLReal * In, DLReal * MPOut, DLReal * EPOut, const int N,const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; DLReal * FFTArray3; int FS; int I; Boolean LogLimit; DLReal CV; /* Controlla se si deve adottare una potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for (FS = 1;FS <= N;FS <<= 1); FS *= 1 << MExp; } else FS = N; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; if ((FFTArray3 = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < N;I++) FFTArray1[I] = In[I]; /* Azzera la parte rimanente */ for (I = N;I < FS;I++) FFTArray1[I] = 0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Calcola i valori per la trasformata di Hilbert */ LogLimit = False; for (I = 0;I < FS;I++) { CV = std::abs(FFTArray1[I]); if (CV <= DRCMinFloat) { LogLimit = True; FFTArray2[I] = (DLReal) log(DRCMinFloat); FFTArray3[I] = DRCMinFloat; } else { FFTArray2[I] = std::log(CV); FFTArray3[I] = CV; } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: log limit reached in Hilbert computation."); /* Calcola la fase per la componente a fase minima */ IFft(FFTArray2,FS); for (I = 1 + FS / 2; I < FS;I++) FFTArray2[I] = -FFTArray2[I]; FFTArray2[0] = 0; FFTArray2[FS / 2] = 0; Fft(FFTArray2,FS); /* Effettua la convoluzione per l'estrazione del sistema a fase minima */ for (I = 0; I < FS;I++) FFTArray2[I] = FFTArray3[I] * std::exp(FFTArray2[I]); /* Dealloca gli array */ delete[] FFTArray3; /* Verifica se deve estrarre la componente EP */ if (EPOut != NULL) { /* Determina la trasformata della parte excess phase */ for (I = 0;I < FS;I++) FFTArray1[I] = std::polar((DLReal) 1.0, std::arg(FFTArray1[I]) - std::arg(FFTArray2[I])); /* Determina la risposta del sistema excess phase */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < N;I++) EPOut[I] = std::real(FFTArray1[I]); } /* Verifica se deve estrarre la componente MP */ if (MPOut != NULL) { /* Determina la risposta del sistema a fase minima */ IFft(FFTArray2,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < N;I++) MPOut[I] = std::real(FFTArray2[I]); } /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } /* Experimental nonsense, ignore */ /* Effettua la decomposizione del segnale In nelle somponenti allmag/allphase */ Boolean AMAPDecomposition(const DLReal * In, DLReal * AMOut, DLReal * APOut, const int N, const int PFactor) { DLComplex * FFTArray1; DLComplex * FFTArray2; int FS; int I,J; DLReal PA[2]; /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= N;FS <<= 1); FS *= 1 << PFactor; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Azzera l'array conversione */ for (I = 0;I < FS;I++) FFTArray1[I] = 0; /* Copia l'array sorgente in quello temporaneo */ for (I = 0,J = (FS - N) / 2;I < N;I++,J++) FFTArray1[J] = In[I]; /* Trasforma l'array risultante */ Radix2Fft(FFTArray1,FS); /* Trasforma nella componente allmag */ PA[0] = 1; PA[1] = -1; for (I = 0;I < FS;I++) FFTArray2[I] = FFTArray1[I] = PA[I % 2] * std::abs(FFTArray1[I]); /* Calcola la componente allmag */ Radix2IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0,J = (FS - N) / 2;I < N;I++,J++) AMOut[I] = std::real(FFTArray1[J]); /* Azzera l'array conversione */ for (I = 0;I < FS;I++) FFTArray1[I] = 0; /* Copia l'array sorgente in quello temporaneo */ for (I = 0,J = (FS - N) / 2;I < N;I++,J++) FFTArray1[J] = In[I]; /* Trasforma l'array risultante */ Radix2Fft(FFTArray1,FS); /* Trasforma nella componente allphase */ for (I = 0;I < FS;I++) FFTArray1[I] = FFTArray1[I] / FFTArray2[I]; /* Calcola la componente allphase */ Radix2IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < N / 2;I++) APOut[I] = std::real(FFTArray1[FS - I]); for (I = N / 2;I < N;I++) APOut[I] = std::real(FFTArray1[I]); /* Rinormalizza il risultato */ // NormFlat(APOut,N,1,PFactor); /* Dealloca gli array temporanei */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } /* Effettua la decomposizione del segnale In nelle somponenti no phase/no mag */ Boolean NPNMDecomposition(const DLReal * In, DLReal * NPOut, DLReal * NMOut, const int N, const int PFactor) { DLComplex * FFTArray1; DLComplex * FFTArray2; int FS; int I; /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= N;FS <<= 1); FS *= 1 << PFactor; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < N;I++) FFTArray1[I] = In[I]; /* Azzera la parte rimanente */ for (I = N;I < FS;I++) FFTArray1[I] = 0; /* Trasforma l'array risultante */ Radix2Fft(FFTArray1,FS); /* Trasforma nella componente no phase */ for (I = 0;I < FS;I++) FFTArray2[I] = std::abs(FFTArray1[I]); /* Calcola la componente allmag */ Radix2IFft(FFTArray2,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < N;I++) NPOut[I] = std::real(FFTArray2[I]); /* Trasforma nella componente allphase */ for (I = 0;I < FS;I++) FFTArray2[I] = FFTArray1[I] / std::abs(FFTArray1[I]); /* Calcola la componente allphase */ Radix2IFft(FFTArray2,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < N;I++) NMOut[I] = std::real(FFTArray2[I]); /* Dealloca gli array temporanei */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } drc-3.2.2/source/lsconv.layout0000644000076400001450000000055213165107243015320 0ustar denisitadm drc-3.2.2/source/glsweep.cbp0000644000076400001450000000456213165106030014707 0ustar denisitadm drc-3.2.2/source/slprefilt.cpp0000644000076400001450000005525313165105213015270 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Prefiltratura a bande tramite sliding lowpass di un segnale */ #include #include "slprefilt.h" #include "level.h" #include "baselib.h" /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Calcolo filtro passa basso finestrato Blackman */ /* Il calcolo viene effettuato usando una ricorsione trigonometrica per migliorare le prestazioni di generazione */ /* La finestratura viene generata solo per met */ void FastLowPassFir(DLReal * Filter,const unsigned int Order,const DLReal Freq, DLReal * Window,const unsigned int WSize) { /* Variabili per le ricorsioni trigonometriche */ DLReal SR1,SS1,SV1; DLReal CR1,CS1,CV1; DLReal CR2,CS2,CV2; /* Indici creazione filtro e finestra */ unsigned int I,J,K; unsigned int HalfOrder = Order / 2; /* Periodo filtro */ DLReal C = (DLReal) (((DLReal) M_PI) * Freq); /* Valore attuale finestra */ DLReal WV; /* Periodo finestratura */ DLReal C1; DLReal C2; /* Verifica che non si tratti del filtro banale */ if (Order == 1) { Filter[0] = (DLReal) 1.0; return; } /* Verifica se deve essere calcolata la finestratura */ if (WSize > 0) { /* Finestratura gi presente, procede con la creazione del filtro */ /* Verifica l'ordine del filtro */ if (Order%2 == 0) { /* Inizializza le variabili per il calcolo della ricorsione per il filtro */ /* R = sin(sd/2); */ SR1 = (DLReal) DLSin(((DLReal) 0.5) * C); /* S = sin(sv); */ /* S = sin(sd) * cos(sv) + (S * (1 - cos(sd))); */ SS1 = ((DLReal) DLSin(C)) * ((DLReal) DLCos(((DLReal) 0.5) * C)) + (SR1 * (((DLReal) 1.0) - ((DLReal) DLCos(C)))); /* V = sin(sv); */ SV1 = SR1; /* R = -4 * R * R; */ SR1 = ((DLReal) -4.0) * SR1 * SR1; /* Ciclo creazione filtro */ for(I = 1,J = HalfOrder - 1,K = HalfOrder; I <= HalfOrder;I++,J--,K++) { /* Calcola e assegna il valore per il filtro */ Filter[J] = Filter[K] = (DLReal) (Window[J] * SV1 / ((I - ((DLReal) 0.5)) * ((DLReal) M_PI))); /* Calcola il valore successivo filtro per ricorsione */ SS1 += SR1 * SV1; SV1 += SS1; } } else { /* Inizializza le variabili per il calcolo della ricorsione per il filtro */ /* S = sin(sv); */ SS1 = ((DLReal) DLSin(C)); /* V = sin(sv); */ SV1 = SS1; /* S = sin(sd) * cos(sv) + (S * (1 - cos(sd))); */ SR1 = ((DLReal) DLCos(C)); SS1 = SS1 * SR1 + (SS1 * (((DLReal) 1.0) - SR1)); /* R = sin(sd/2); */ /* R = -4 * R * R; */ SR1 = (DLReal) DLSin(((DLReal) 0.5) * C); SR1 = ((DLReal) -4.0) * SR1 * SR1; /* Ciclo creazione filtro */ for(I = 1,J = HalfOrder - 1,K = HalfOrder + 1; I <= HalfOrder;I++,J--,K++) { /* Calcola e assegna il valore per il filtro */ Filter[J] = Filter[K] = (DLReal) (Window[J] * SV1 / (I * ((DLReal) M_PI))); /* Calcola il valore successivo filtro per ricorsione */ SS1 += SR1 * SV1; SV1 += SS1; } /* Assegna il valore centrale */ Filter[HalfOrder] = Freq; } } else { /* Finestratura da calcolare, inizializza il periodo */ C1 = (DLReal) (2 * ((DLReal) M_PI) / (Order - 1)); C2 = (DLReal) (4 * ((DLReal) M_PI) / (Order - 1)); /* Verifica l'ordine del filtro */ if (Order%2 == 0) { /* Inizializza le variabili per il calcolo della ricorsione per la finestratura */ /* R = sin(cd/2); */ /* R = -4 * R * R; */ CR1 = (DLReal) DLSin(((DLReal) 0.5) * C1); CR1 = ((DLReal) -4.0) * CR1 * CR1; /* S = cos(cv); */ CS1 = (DLReal) DLCos(HalfOrder * C1); /* S = (S * (1 - cos(cd))) - sin(cv) * sin(cd); */ CS1 = (CS1 * (((DLReal) 1.0) - ((DLReal) DLCos(C1)))) - ((DLReal) DLSin(HalfOrder * C1)) * ((DLReal) DLSin(C1)); /* V = cos(cv); */ CV1 = (DLReal) DLCos(HalfOrder * C1); /* R = sin(cd/2); */ /* R = -4 * R * R; */ CR2 = (DLReal) DLSin(((DLReal) 0.5) * C2); CR2 = ((DLReal) -4.0) * CR2 * CR2; /* S = cos(cv); */ CS2 = (DLReal) DLCos(HalfOrder * C2); /* S = (S * (1 - cos(cd))) - sin(cv) * sin(cd); */ CS2 = (CS2 * (((DLReal) 1.0) - ((DLReal) DLCos(C2)))) - ((DLReal) DLSin(HalfOrder * C2)) * ((DLReal) DLSin(C2)); /* V = cos(cv); */ CV2 = (DLReal) DLCos(HalfOrder * C2); /* Inizializza le variabili per il calcolo della ricorsione per il filtro */ /* R = sin(sd/2); */ SR1 = (DLReal) DLSin(((DLReal) 0.5) * C); /* S = sin(sv); */ /* S = sin(sd) * cos(sv) + (S * (1 - cos(sd))); */ SS1 = ((DLReal) DLSin(C)) * ((DLReal) DLCos(((DLReal) 0.5) * C)) + (SR1 * (((DLReal) 1.0) - ((DLReal) DLCos(C)))); /* V = sin(sv); */ SV1 = SR1; /* R = -4 * R * R; */ SR1 = ((DLReal) -4.0) * SR1 * SR1; /* Ciclo creazione filtro */ for(I = 1,J = HalfOrder - 1,K = HalfOrder; I <= HalfOrder;I++,J--,K++) { /* Calcola e assegna il valore della finestra */ Window[J] = WV = (DLReal) (((DLReal) 0.42) - ((DLReal) 0.5) * CV1 + ((DLReal) 0.08) * CV2); /* Calcola e assegna il valore per il filtro */ Filter[J] = Filter[K] = (DLReal) (WV * SV1 / ((I - ((DLReal) 0.5)) * ((DLReal) M_PI))); /* Calcola il valore successivo filtro per ricorsione */ SS1 += SR1 * SV1; SV1 += SS1; /* Calcola il valore successivo finestra per ricorsione */ CS1 += CR1 * CV1; CV1 += CS1; CS2 += CR2 * CV2; CV2 += CS2; } } else { /* Inizializza le variabili per il calcolo della ricorsione per la finestratura */ /* R = sin(cd/2); */ /* R = -4 * R * R; */ CR1 = (DLReal) DLSin(((DLReal) 0.5) * C1); CR1 = ((DLReal) -4.0) * CR1 * CR1; /* S = cos(cv); */ CS1 = (DLReal) DLCos((HalfOrder + 1) * C1); /* S = (S * (1 - cos(cd))) - sin(cv) * sin(cd); */ CS1 = (CS1 * (((DLReal) 1.0) - ((DLReal) DLCos(C1)))) - ((DLReal) DLSin((HalfOrder + 1) * C1)) * ((DLReal) DLSin(C1)); /* V = cos(cv); */ CV1 = (DLReal) DLCos((HalfOrder + 1) * C1); /* R = sin(cd/2); */ /* R = -4 * R * R; */ CR2 = (DLReal) DLSin(((DLReal) 0.5) * C2); CR2 = ((DLReal) -4.0) * CR2 * CR2; /* S = cos(cv); */ CS2 = (DLReal) DLCos((HalfOrder + 1) * C2); /* S = (S * (1 - cos(cd))) - sin(cv) * sin(cd); */ CS2 = (CS2 * (((DLReal) 1.0) - ((DLReal) DLCos(C2)))) - ((DLReal) DLSin((HalfOrder + 1) * C2)) * ((DLReal) DLSin(C2)); /* V = cos(cv); */ CV2 = (DLReal) DLCos((HalfOrder + 1) * C2); /* Inizializza le variabili per il calcolo della ricorsione per il filtro */ /* S = sin(sv); */ SS1 = ((DLReal) DLSin(C)); /* V = sin(sv); */ SV1 = SS1; /* S = sin(sd) * cos(sv) + (S * (1 - cos(sd))); */ SR1 = ((DLReal) DLCos(C)); SS1 = SS1 * SR1 + (SS1 * (((DLReal) 1.0) - SR1)); /* R = sin(sd/2); */ /* R = -4 * R * R; */ SR1 = (DLReal) DLSin(((DLReal) 0.5) * C); SR1 = ((DLReal) -4.0) * SR1 * SR1; /* Ciclo creazione filtro */ for(I = 1,J = HalfOrder - 1,K = HalfOrder + 1; I <= HalfOrder;I++,J--,K++) { /* Calcola e assegna il valore della finestra */ Window[J] = WV = (DLReal) (((DLReal) 0.42) - ((DLReal) 0.5) * CV1 + ((DLReal) 0.08) * CV2); /* Calcola e assegna il valore per il filtro */ Filter[J] = Filter[K] = (DLReal) (WV * SV1 / (I * ((DLReal) M_PI))); /* Calcola il valore successivo filtro per ricorsione */ SS1 += SR1 * SV1; SV1 += SS1; /* Calcola il valore successivo finestra per ricorsione */ CS1 += CR1 * CV1; CV1 += CS1; CS2 += CR2 * CV2; CV2 += CS2; } /* Assegna il valore centrale del filtro */ Filter[HalfOrder] = Freq; } } } /* Prefiltratura a bande tramite sliding lowpass di un segnale */ void SLPreFilt(DLReal * InImp, const int IBS, const int FBS, const int FilterLen, const int BandSplit, const DLReal WindowExponent, const int SampleFreq, const DLReal StartFreq, const DLReal EndFreq, int WindowGap, DLReal FSharpness, DLReal * OutImp, const WindowType WType, const SLPPrefilteringType SLPType) { /* Array filtro FIR */ DLReal * FIRFilter; /* Array finestratura filtro */ DLReal * FWin; /* Dimensione effettiva filtro FIR */ int EFL, HEFL; /* Dimensione corrente filtro FIR */ int CFL; int CHFL; int CFLM; /* Dimensione attuale finestra */ int CWL; /* Dimensione effettiva finestra */ int EWL; /* Indici convoluzione */ int I,J,IS,FS,EI; /* Dimensioni blocco in uscita */ int NR,HNR; /* Posizione semiblocchi destro e sinistro */ int OCP; /* Numero banda corrente */ int Band; /* Frequenza di taglio. */ DLReal BCut = 0; /* Larghezza banda */ DLReal BWidth; /* Inizio e fine filtratura */ DLReal FilterBegin; DLReal FilterEnd; /* Coefficienti calcolo frequenza di taglio su finestra */ DLReal A = 0; DLReal Q = 0; DLReal B = 0; int HFBS; int HIBS; /* Sommatoria filtratura */ DLReal Sum; /* Variabili per il Kahan summation algorithm */ DLReal SC; DLReal SY; DLReal ST; /* Calcola inizio e fine della prefiltratura */ FilterBegin = (2 * StartFreq) / SampleFreq; FilterEnd = (2 * EndFreq) / SampleFreq; /* Calcola la dimensione effettiva filtro FIR */ if (FilterLen % 2 == 0) { EFL = FilterLen - 1; /* Azzera l'ultimo campione del blocco in uscita in quanto non utilizzato */ OutImp[(IBS + FilterLen - 1) - 1] = 0; } else EFL = FilterLen; HEFL = EFL / 2; /* Calcola la dimensione del blocco in uscita */ NR = IBS + EFL - 1; /* Calcola il centro dei semiblocchi */ HNR = NR / 2; /* Alloca gli array temporanei */ FIRFilter = new DLReal[EFL]; FWin = new DLReal[HEFL]; /* Imposta i parametri iniziali per la visualizzazione */ BWidth = (DLReal) pow(2,1.0/BandSplit); Band = 0; /* Calcola le dimensioni finestratura effettive */ HFBS = FBS / 2; HIBS = IBS / 2; /* Effettua la finestratura iniziale del segnale in ingresso */ sputs("Input signal prewindowing."); SpacedBlackmanWindow(InImp,IBS,WindowGap,WType); /* Verifica il tipo di curva di prefiltratura */ switch (SLPType) { /* Proporzionale */ case SLPProportional: /* Calcola i coefficienti per il calcolo finestratura */ B = (DLReal) exp(log(FilterBegin / FilterEnd) / WindowExponent); Q = (DLReal) ((B * HIBS - HFBS) / (1.0 - B)); A = (DLReal) (1.0 / (FilterEnd * pow(HFBS + Q,WindowExponent))); break; /* Bilineare */ case SLPBilinear: A = (DLReal) (HIBS - HFBS); B = (FilterEnd - FilterBegin); Q = (DLReal) ((pow(WindowExponent,4.0) * (FilterBegin / FilterEnd)) - 1.0); break; } /* Finestratura sinistra */ if ((WType == WLeft) || (WType == WFull)) { /* Prepara gli indici per la convoluzione */ EWL = (int) floor(FSharpness * HNR); CHFL = HEFL; /* Verifica che il filtro stia all'interno della finestratura corrente */ if (CHFL >= EWL) { /* Ricalcola la dimensione del filtro */ if (EWL > 1) CHFL = EWL - 1; else CHFL = 1; CFL = 1 + (CHFL * 2); } else /* Usa la dimensione base */ CFL = EFL; /* Ricalcola il filtro e la finestra */ FastLowPassFir(FIRFilter,CFL,FilterBegin,FWin,0); /* Segnala lo stato */ sputs("L - Initial lowpass convolution..."); /* Ciclo di convoluzione lowpass iniziale */ for(I = 0,CWL = HNR,OCP = 0;I < (HNR - HIBS);I++,CWL--,OCP++) { /* Calcola la finestratura effettiva corrente */ EWL = (int) floor(FSharpness * CWL); /* Verifica che il filtro stia all'interno della finestratura corrente */ if (CHFL >= EWL) { /* Ricalcola la dimensione del filtro */ if (EWL > 1) CHFL = EWL - 1; else CHFL = 1; CFL = 1 + (CHFL * 2); /* Ricalcola il filtro e la finestra */ FastLowPassFir(FIRFilter,CFL,FilterBegin,FWin,0); } /* Verifica se si pu utilizzare il filtro completo */ if (OCP - CHFL >= HEFL) { /* Imposta gli indici per il filtro completo */ CFLM = CFL; IS = OCP - (CHFL + HEFL); FS = 0; } else { /* Imposta gli indici per il filtro parziale */ CFLM = CFL; IS = 0; FS = (CHFL + HEFL) - OCP; } /* Esegue la convoluzione, Kahan summation algorithm */ Sum = (DLReal) 0.0; SC = (DLReal) 0.0; for (J = FS,EI = IS;J < CFLM;J++,EI++) { SY = (InImp[EI] * FIRFilter[J]) - SC; ST = Sum + SY; SC = (ST - Sum) - SY; Sum = ST; } OutImp[OCP] = Sum; } /* Imposta i parametri iniziali per la visualizzazione */ Band = 0; /* Ciclo di convoluzione sliding lowpass */ for(I = HNR - HIBS,CWL = HIBS,OCP = HNR - HIBS;I < (HNR - HFBS);I++,CWL--,OCP++) { /* Calcola la finestratura effettiva corrente */ EWL = (int) floor(FSharpness * CWL); /* Verifica il tipo di curva di prefiltratura */ switch (SLPType) { /* Proporzionale */ case SLPProportional: /* Calcola la frequenza di taglio */ BCut = (DLReal) 1.0 / (A * pow(CWL + Q,WindowExponent)); break; /* Bilineare */ case SLPBilinear: /* Calcola la frequenza di taglio */ BCut = (DLReal) FilterBegin + (B * (((HIBS - CWL) / A) * (1 + Q)) / (1 + ((HIBS - CWL) / A) * Q)); break; } /* Verifica che il filtro stia all'interno della finestratura corrente */ if (CHFL >= EWL) { /* Ricalcola la dimensione del filtro */ if (EWL > 1) CHFL = EWL - 1; else CHFL = 1; CFL = 1 + (CHFL * 2); /* Ricalcola il filtro e la finestra */ FastLowPassFir(FIRFilter,CFL,BCut,FWin,0); } else /* Ricalcola il filtro usando la finestra corrente */ FastLowPassFir(FIRFilter,CFL,BCut,FWin,CFL); /* Verifica visualizzazione stato prefiltratura */ if (BCut >= (DLReal) (FilterBegin * pow(BWidth,Band))) { /* Segnala lo stato */ printf("L - Band: %3d, %7.1f Hz, width: %6d, FIR, ", (int) Band, (double) (BCut * SampleFreq) / 2, CWL); /* Passa alla banda successiva */ Band++; /* Inizio convoluzione */ sputs("convolution..."); } /* Verifica se si pu utilizzare il filtro completo */ if (OCP - CHFL >= HEFL) { /* Imposta gli indici per il filtro completo */ CFLM = CFL; IS = OCP - (CHFL + HEFL); FS = 0; } else { /* Imposta gli indici per il filtro parziale */ CFLM = CFL; IS = 0; FS = (CHFL + HEFL) - OCP; } /* Esegue la convoluzione, Kahan summation algorithm */ Sum = (DLReal) 0.0; SC = (DLReal) 0.0; for (J = FS,EI = IS;J < CFLM;J++,EI++) { SY = (InImp[EI] * FIRFilter[J]) - SC; ST = Sum + SY; SC = (ST - Sum) - SY; Sum = ST; } OutImp[OCP] = Sum; } /* Verifica il tipo di curva di prefiltratura */ switch (SLPType) { /* Proporzionale */ case SLPProportional: /* Calcola la frequenza di taglio */ BCut = (DLReal) 1.0 / (A * pow(CWL + Q,WindowExponent)); break; /* Bilineare */ case SLPBilinear: /* Calcola la frequenza di taglio */ BCut = (DLReal) FilterBegin + (B * (((HIBS - CWL) / A) * (1 + Q)) / (1 + ((HIBS - CWL) / A) * Q)); break; } /* Segnala lo stato finale */ printf("F - Band: %3d, %7.1f Hz, width: %6d, FIR, ", (int) Band, (double) (BCut * SampleFreq) / 2, CWL); sputs("completed."); } /* Effettua la convoluzione, lato destro */ if ((WType == WRight) || (WType == WFull)) { /* Prepara gli indici per la convoluzione */ EWL = (int) floor(FSharpness * HNR); CHFL = HEFL; /* Verifica che il filtro stia all'interno della finestratura corrente */ if (CHFL >= EWL) { /* Ricalcola la dimensione del filtro */ if (EWL > 1) CHFL = EWL - 1; else CHFL = 1; CFL = 1 + (CHFL * 2); } else /* Usa la dimensione base */ CFL = EFL; /* Ricalcola il filtro e la finestra */ FastLowPassFir(FIRFilter,CFL,FilterBegin,FWin,0); /* Segnala lo stato */ sputs("R - Initial lowpass convolution..."); /* Ciclo di convoluzione lowpass iniziale */ for(I = 0,CWL = HNR,OCP = NR - 1;I < (HNR - HIBS);I++,CWL--,OCP--) { /* Calcola la finestratura effettiva corrente */ EWL = (int) floor(FSharpness * CWL); /* Verifica che il filtro stia all'interno della finestratura corrente */ if (CHFL >= EWL) { /* Ricalcola la dimensione del filtro */ if (EWL > 1) CHFL = EWL - 1; else CHFL = 1; CFL = 1 + (CHFL * 2); /* Ricalcola il filtro e la finestra */ FastLowPassFir(FIRFilter,CFL,FilterBegin,FWin,0); } /* Verifica se si pu utilizzare il filtro completo */ if (OCP + CHFL < HEFL + IBS) { /* Imposta gli indici per il filtro completo */ CFLM = CFL; IS = OCP - (CHFL + HEFL); FS = 0; } else { /* Imposta gli indici per il filtro parziale */ CFLM = HEFL + IBS + CHFL - OCP; IS = OCP - (CHFL + HEFL); FS = 0; } /* Esegue la convoluzione, Kahan summation algorithm */ Sum = (DLReal) 0.0; SC = (DLReal) 0.0; for (J = FS,EI = IS;J < CFLM;J++,EI++) { SY = (InImp[EI] * FIRFilter[J]) - SC; ST = Sum + SY; SC = (ST - Sum) - SY; Sum = ST; } OutImp[OCP] = Sum; } /* Imposta i parametri iniziali per la visualizzazione */ Band = 0; /* Ciclo di convoluzione sliding lowpass */ for(I = HNR - HIBS,CWL = HIBS,OCP = NR - 1 - (HNR - HIBS);I < (HNR - HFBS);I++,CWL--,OCP--) { /* Calcola la finestratura effettiva corrente */ EWL = (int) floor(FSharpness * CWL); /* Verifica il tipo di curva di prefiltratura */ switch (SLPType) { /* Proporzionale */ case SLPProportional: /* Calcola la frequenza di taglio */ BCut = (DLReal) 1.0 / (A * pow(CWL + Q,WindowExponent)); break; /* Bilineare */ case SLPBilinear: /* Calcola la frequenza di taglio */ BCut = (DLReal) FilterBegin + (B * (((HIBS - CWL) / A) * (1 + Q)) / (1 + ((HIBS - CWL) / A) * Q)); break; } /* Verifica che il filtro stia all'interno della finestratura corrente */ if (CHFL >= EWL) { /* Ricalcola la dimensione del filtro */ if (EWL > 1) CHFL = EWL - 1; else CHFL = 1; CFL = 1 + (CHFL * 2); /* Ricalcola il filtro e la finestra */ FastLowPassFir(FIRFilter,CFL,BCut,FWin,0); } else /* Ricalcola il filtro usando la finestra corrente */ FastLowPassFir(FIRFilter,CFL,BCut,FWin,CFL); /* Verifica visualizzazione stato prefiltratura */ if (BCut >= (DLReal) (FilterBegin * pow(BWidth,Band))) { /* Segnala lo stato */ printf("R - Band: %3d, %7.1f Hz, width: %6d, FIR, ", (int) Band, (double) (BCut * SampleFreq) / 2, CWL); /* Passa alla banda successiva */ Band++; /* Inizio convoluzione */ sputs("convolution..."); } /* Verifica se si pu utilizzare il filtro completo */ if (OCP + CHFL < HEFL + IBS) { /* Imposta gli indici per il filtro completo */ CFLM = CFL; IS = OCP - (CHFL + HEFL); FS = 0; } else { /* Imposta gli indici per il filtro parziale */ CFLM = HEFL + IBS + CHFL - OCP; IS = OCP - (CHFL + HEFL); FS = 0; } /* Esegue la convoluzione, Kahan summation algorithm */ Sum = (DLReal) 0.0; SC = (DLReal) 0.0; for (J = FS,EI = IS;J < CFLM;J++,EI++) { SY = (InImp[EI] * FIRFilter[J]) - SC; ST = Sum + SY; SC = (ST - Sum) - SY; Sum = ST; } OutImp[OCP] = Sum; } /* Verifica il tipo di curva di prefiltratura */ switch (SLPType) { /* Proporzionale */ case SLPProportional: /* Calcola la frequenza di taglio */ BCut = (DLReal) 1.0 / (A * pow(CWL + Q,WindowExponent)); break; /* Bilineare */ case SLPBilinear: /* Calcola la frequenza di taglio */ BCut = (DLReal) FilterBegin + (B * (((HIBS - CWL) / A) * (1 + Q)) / (1 + ((HIBS - CWL) / A) * Q)); break; } /* Segnala lo stato finale */ printf("F - Band: %3d, %7.1f Hz, width: %6d, FIR, ", (int) Band, (double) (BCut * SampleFreq) / 2, CWL); sputs("completed."); } /* Segnala lo stato finale */ sputs("Final allpass convolution..."); /* Copia la parte rimanente della risposta */ switch (WType) { case WLeft: for (I = HNR - HFBS,J = HIBS - HFBS;J < IBS;I++,J++) OutImp[I] = InImp[J]; for (I = NR - HEFL;I < NR;I++) OutImp[I] = (DLReal) 0.0; break; case WRight: for (I = 0;I < HEFL;I++) OutImp[I] = (DLReal) 0.0; FS = HFBS + (IBS % 2); for (I = HEFL,J = 0;I < (HNR + FS);I++,J++) OutImp[I] = InImp[J]; break; case WFull: FS = HFBS + (IBS % 2); for (I = HNR - HFBS,J = HIBS - HFBS;I < (HNR + FS);I++,J++) OutImp[I] = InImp[J]; break; } /* Dealloca gli array intermedi */ delete[] FIRFilter; delete[] FWin; } drc-3.2.2/source/fir.h0000644000076400001450000000764513162156311013515 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : Fir.h Autore : Sbragion Denis Descrizione : Funzioni per il calcolo di filtri fir. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #ifndef Fir_h #define Fir_h #include "boolean.h" #include "dsplib.h" // Definizione tipo interpolazione typedef enum { Linear, Logarithmic, SplineLinear, SplineLogarithmic, PCHIPLinear, PCHIPLogarithmic } InterpolationType; // Ritornano i filtri fir a fase lineare di ordine Order corrispondenti // al nome della funzione. Tutti i filtri sono ricavati con la sola // finestra rettangolare. // Per i filtri HighPass e BandStop Order deve essere dispari. // Se non lo e` viene calcolato un filtro con Order-1 coefficienti // trascurando l' ultimo che viene posto a 0. // Order deve comunque essere maggiore o uguale a 2. void LowPassFir(DLReal * Filter,unsigned int Order,DLReal Freq); void HighPassFir(DLReal * Filter,unsigned int Order,DLReal Freq); void BandPassFir(DLReal * Filter,unsigned int Order,DLReal Low, DLReal High); void BandStopFir(DLReal * Filter,unsigned int Order,DLReal Low, DLReal High); // Ritorna il trasformatore di Hilbert di ordine Order ricavato con la // sola finestra rettangolare. // Order deve essere dispari altrimenti l' ultimo coefficiente viene // ignorato e posto uguale a 0. Inoltre Order deve essere maggiore di 2. void HilbertFir(DLReal * Filter,unsigned int Order); // Genera un filtro Fir con risposta generica tramite IFft e // finestratura. L' ordine Order deve essere maggiore o uguale a 2. // Il filtro e` ricavato con la sola finestra rettangolare. Si ricordi // che i filtri di ordine dispari presentano generalmente un // comportamento piu` regolare. // F rappresenta l' array delle frequenze su cui costruire la risposta // del filtro. Deve essere in ordine crescente con il primo // coefficiente 0 e l' ultimo, corrispondente a meta` della frequenza // di campionamento, uguale a 1. M[I] e P[I] rappresentano // guadagno e fase desiderati nei corrispondenti punti F[I]. // Ritorna False in caso di errori. // Se Is e` 0 l' array per l' interpolazione intermedia viene preso // con dimensione pari alla piu` piccola potenza di 2 che supera Order, // altrimenti viene preso con dimensione Is. Is non deve comunque essere // inferiore a Order. Per avere una elevata precisione nella // ricostruzione della risposta utilizzare un elevato valore di Is. // Se Is e` una potenza di 2 il calcolo risulta molto piu` rapido. Boolean GenericFir(DLReal * Filter,unsigned int Order,DLReal * F, DLReal * M, DLReal * P,unsigned int Np,unsigned int Is = 0, InterpolationType It = Linear); #endif /***************************************************************************/ drc-3.2.2/source/spline.h0000644000076400001450000001216013164710040014210 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2017 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@neomerica.it ****************************************************************************/ /* Spline routines */ #ifndef Spline_h #define Spline_h /* Inclusioni */ #include "dsplib.h" #include "boolean.h" /* Tipo spline da generare */ typedef enum { SplineBDef, SplineBNat } CSplineType; /* Valore della spline lineare nel punto X */ DLReal L1SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal X); /* Valore della spline lineare nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void AL1SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y); /* Prepara la base per la spline cubica interpolante, ponendola in SPD2YN */ Boolean SplinePrepare(const DLReal * XN, const DLReal * YN, const int N, const DLReal SPD1Y1, const DLReal SPD1YN, const CSplineType SPType, DLReal * SPD2YN); /* Valore della spline cubica interpolante nel punto X */ DLReal SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * SPD2YN, const DLReal X); /* Valore della spline cubica interpolante nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void ASplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * SPD2YN, const DLReal * X, const int XS, DLReal * Y); /* Valore della B spline cubica uniforme nel punto X */ DLReal B3SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal X); /* Valore della B spline cubica uniforme nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void AB3SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y); /* Valore della B spline cubica di tipo Catmull Rom nel punto X */ DLReal B3CRSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal X); /* Valore della B spline cubica di tipo Catmull Rom nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void AB3CRSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y); /* Interpolazione su scala lineare tramite B spline cubica uniforme con riparametrizzazione arc length tramite B spline cubica Catmull-Rom interpolante */ Boolean AB3CRMSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y); /* Interpolazione su scala lineare tramite Hermite spline cubica monotonica */ void APCHIPSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y); /* Interpolazione su scala lineare tramite B spline cubica uniforme con riparametrizzazione arc length tramite spline cubica Hermite monotonica */ Boolean AB3HSMSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y); /* Definizione tipo spline da utilizzare */ typedef enum { CSLLinear, /* Lineare */ CSLCSpline, /* Spline cubica interpolante classica, classe C2, non monotonica */ CSLBSpline, /* B Spline cubica approssimante, classe C2, non interpolante */ CSLCRSpline, /* CatmullRom, interpolante, non monotonica */ CSLHSSpline /* Hermite spline, interpolante, monotonica (PCHIP) */ } CSLSplineType; /* Definizione tipo asse da utilizzare */ typedef enum { CSLLinXLinY, CSLLogXLinY, CSLLinXLogY, CSLLogXLogY } CSLAxisType; /* Funzione generica interpolazione */ /* Nel caso si utilizzi un asse logaritmico i valori su tale asse devono essere strettamente maggiori di 0 */ Boolean CSLASplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y, const CSLSplineType SplineType, const CSLAxisType AxisType); /* Funzione generica interpolazione, versione complessa */ /* Nel caso si utilizzi un asse logaritmico i valori di ampiezza su tale asse devono essere strettamente maggiori di 0. I valori di fase vengono sempre considerati su ascissa lineare */ Boolean CSLCASplineValue(const DLReal * XN, const DLReal * MN, const DLReal * PN, const int N, const DLReal * X, const int XS, DLComplex * Y, const CSLSplineType SplineType, const CSLAxisType AxisType); #endif drc-3.2.2/source/fft.h0000644000076400001450000000655413162156312013513 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : Fft.h Autore : Sbragion Denis Descrizione : Funzioni per fft, ifft etc. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #ifndef Fft_h #define Fft_h #include "boolean.h" #include "dsplib.h" // Ritorna la potenza N-esima di X // Complessita` : O(log2(N)). DLComplex Power(DLComplex X,unsigned int N); // Ritorna la J-esima radice N-esima dell' unita`. // La prima ha indice 0, l' ultima N-1, poi si ripetono ciclicamente. DLComplex UnitRoot(unsigned int I,unsigned int N); // Ritorna il primo divisore di N. unsigned int FirstFactor(unsigned int N); // Fft e IFft a radice 2 dell' array P di lunghezza N // N deve essere una potenza di 2 // Complessita` : O(N*log2(N)). void Radix2Fft(DLComplex P[],unsigned int N); void Radix2IFft(DLComplex P[],unsigned int N); // Fft e IFft a radice mista dell' array P di lunghezza N. // N puo` essere qualsiasi ma se contiene pochi fattori le // prestazione si riducono enormemente. In particolare per N primo // la funzione ha complessita` O(N^2) come per Dft() e IDft(). // Se N contiene molti fattori uguali a 2 le prestazioni aumentano. // Necessita di spazio libero in memoria per un array di complessi di // lunghezza pari al piu` grande fattore di N. // Se non vi e` spazio la funzione si arresta e ritorna False, altrimenti // ritorna True. // Se N e` una potenza di 2 la versione a radice 2 e` circa il 5% // piu` veloce. Boolean Fft(DLComplex P[],unsigned int N); Boolean IFft(DLComplex P[],unsigned int N); // Valutazione del polinomio P nel punto X col metodo di Horner // Il polinomio e` considerato nella forma : // P[0] + P[1]*X + P[2]*X^2 + ... + P[N-1]*X^(N-1) // Complessita` : O(N). DLComplex PolyEval(DLComplex P[],unsigned int N,DLComplex X); // Dft e IDft del polinomio P (Valutazione nelle radici dell'unita `). // Richiede spazio in memoria per almemo N complessi. Se l' allocazione // non ha sucesso ritorna False altrimenti ritorna True; // Complessita` : O(N^2). Boolean Dft(DLComplex P[],unsigned int N); Boolean IDft(DLComplex P[],unsigned int N); #endif /***************************************************************************/ drc-3.2.2/source/config.h0000644000076400001450000000017013164704745014200 0ustar denisitadm/* Dummy config.h file */ /* Macro needed by the GSL FFT library */ #define RETURN_IF_NULL(x) if (!x) { return ; } drc-3.2.2/source/test/0000755000076400001450000000000013165107361013533 5ustar denisitadmdrc-3.2.2/source/test/cfgtest.sh0000644000076400001450000001766613163131545015545 0ustar denisitadm# General DRC configuration testing. # This file need the DRC executable to be either in the # current path or in the current directory. # It also needs a dirac.pcm file with a Dirac delta few seconds long in it. # This could be created in octave with: # dcir = zeros(2^18,1); # dcir(round(length(dcir) / 2)) = 1.0; # savepcm(dcir,'..\..\test\dirac.pcm'); # 44.1 kHz ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSOutFile=dxp-erb-44.1.pcm --MSOutFile=dmp-erb-44.1.pcm --TCOutFile=dtc-erb-44.1.pcm "../config/44.1 kHz/erb-44.1.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSOutFile=dxp-minimal-44.1.pcm --MSOutFile=dmp-minimal-44.1.pcm --TCOutFile=dtc-minimal-44.1.pcm "../config/44.1 kHz/minimal-44.1.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSOutFile=dxp-soft-44.1.pcm --MSOutFile=dmp-soft-44.1.pcm --TCOutFile=dtc-soft-44.1.pcm "../config/44.1 kHz/soft-44.1.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSOutFile=dxp-normal-44.1.pcm --MSOutFile=dmp-normal-44.1.pcm --TCOutFile=dtc-normal-44.1.pcm "../config/44.1 kHz/normal-44.1.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSOutFile=dxp-strong-44.1.pcm --MSOutFile=dmp-strong-44.1.pcm --TCOutFile=dtc-strong-44.1.pcm "../config/44.1 kHz/strong-44.1.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSOutFile=dxp-extreme-44.1.pcm --MSOutFile=dmp-extreme-44.1.pcm --TCOutFile=dtc-extreme-44.1.pcm "../config/44.1 kHz/extreme-44.1.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSPointsFile="../target/44.1 kHz/flat-44.1.txt" --PSOutFile=dxp-insane-44.1.pcm --MSOutFile=dmp-insane-44.1.pcm --TCOutFile=dtc-insane-44.1.pcm "../config/44.1 kHz/insane-44.1.drc" # 48.0 kHz ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSOutFile=dxp-erb-48.0.pcm --MSOutFile=dmp-erb-48.0.pcm --TCOutFile=dtc-erb-48.0.pcm "../config/48.0 kHz/erb-48.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSOutFile=dxp-minimal-48.0.pcm --MSOutFile=dmp-minimal-48.0.pcm --TCOutFile=dtc-minimal-48.0.pcm "../config/48.0 kHz/minimal-48.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSOutFile=dxp-soft-48.0.pcm --MSOutFile=dmp-soft-48.0.pcm --TCOutFile=dtc-soft-48.0.pcm "../config/48.0 kHz/soft-48.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSOutFile=dxp-normal-48.0.pcm --MSOutFile=dmp-normal-48.0.pcm --TCOutFile=dtc-normal-48.0.pcm "../config/48.0 kHz/normal-48.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSOutFile=dxp-strong-48.0.pcm --MSOutFile=dmp-strong-48.0.pcm --TCOutFile=dtc-strong-48.0.pcm "../config/48.0 kHz/strong-48.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSOutFile=dxp-extreme-48.0.pcm --MSOutFile=dmp-extreme-48.0.pcm --TCOutFile=dtc-extreme-48.0.pcm "../config/48.0 kHz/extreme-48.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSPointsFile="../target/48.0 kHz/flat-48.0.txt" --PSOutFile=dxp-insane-48.0.pcm --MSOutFile=dmp-insane-48.0.pcm --TCOutFile=dtc-insane-48.0.pcm "../config/48.0 kHz/insane-48.0.drc" # 88.2 kHz ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSOutFile=dxp-erb-88.2.pcm --MSOutFile=dmp-erb-88.2.pcm --TCOutFile=dtc-erb-88.2.pcm "../config/88.2 kHz/erb-88.2.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSOutFile=dxp-minimal-88.2.pcm --MSOutFile=dmp-minimal-88.2.pcm --TCOutFile=dtc-minimal-88.2.pcm "../config/88.2 kHz/minimal-88.2.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSOutFile=dxp-soft-88.2.pcm --MSOutFile=dmp-soft-88.2.pcm --TCOutFile=dtc-soft-88.2.pcm "../config/88.2 kHz/soft-88.2.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSOutFile=dxp-normal-88.2.pcm --MSOutFile=dmp-normal-88.2.pcm --TCOutFile=dtc-normal-88.2.pcm "../config/88.2 kHz/normal-88.2.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSOutFile=dxp-strong-88.2.pcm --MSOutFile=dmp-strong-88.2.pcm --TCOutFile=dtc-strong-88.2.pcm "../config/88.2 kHz/strong-88.2.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSOutFile=dxp-extreme-88.2.pcm --MSOutFile=dmp-extreme-88.2.pcm --TCOutFile=dtc-extreme-88.2.pcm "../config/88.2 kHz/extreme-88.2.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSPointsFile="../target/88.2 kHz/flat-88.2.txt" --PSOutFile=dxp-insane-88.2.pcm --MSOutFile=dmp-insane-88.2.pcm --TCOutFile=dtc-insane-88.2.pcm "../config/88.2 kHz/insane-88.2.drc" # 96.0 kHz ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSOutFile=dxp-erb-96.0.pcm --MSOutFile=dmp-erb-96.0.pcm --TCOutFile=dtc-erb-96.0.pcm "../config/96.0 kHz/erb-96.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSOutFile=dxp-minimal-96.0.pcm --MSOutFile=dmp-minimal-96.0.pcm --TCOutFile=dtc-minimal-96.0.pcm "../config/96.0 kHz/minimal-96.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSOutFile=dxp-soft-96.0.pcm --MSOutFile=dmp-soft-96.0.pcm --TCOutFile=dtc-soft-96.0.pcm "../config/96.0 kHz/soft-96.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSOutFile=dxp-normal-96.0.pcm --MSOutFile=dmp-normal-96.0.pcm --TCOutFile=dtc-normal-96.0.pcm "../config/96.0 kHz/normal-96.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSOutFile=dxp-strong-96.0.pcm --MSOutFile=dmp-strong-96.0.pcm --TCOutFile=dtc-strong-96.0.pcm "../config/96.0 kHz/strong-96.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSOutFile=dxp-extreme-96.0.pcm --MSOutFile=dmp-extreme-96.0.pcm --TCOutFile=dtc-extreme-96.0.pcm "../config/96.0 kHz/extreme-96.0.drc" ./drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSPointsFile="../target/96.0 kHz/flat-96.0.txt" --PSOutFile=dxp-insane-96.0.pcm --MSOutFile=dmp-insane-96.0.pcm --TCOutFile=dtc-insane-96.0.pcm "../config/96.0 kHz/insane-96.0.drc"drc-3.2.2/source/test/cfgtest.bat0000644000076400001450000001772213163131506015667 0ustar denisitadm@echo off rem General DRC configuration testing. rem This file need the DRC executable to be either in the rem current path or in the current directory. rem It also needs a dirac.pcm file with a Dirac delta few seconds long in it. rem This could be created in octave with: rem dcir = zeros(2^18,1); rem dcir(round(length(dcir) / 2)) = 1.0; rem savepcm(dcir,'..\..\test\dirac.pcm'); rem 44.1 kHz drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSOutFile=dxp-erb-44.1.pcm --MSOutFile=dmp-erb-44.1.pcm --TCOutFile=dtc-erb-44.1.pcm "..\config\44.1 kHz\erb-44.1.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSOutFile=dxp-minimal-44.1.pcm --MSOutFile=dmp-minimal-44.1.pcm --TCOutFile=dtc-minimal-44.1.pcm "..\config\44.1 kHz\minimal-44.1.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSOutFile=dxp-soft-44.1.pcm --MSOutFile=dmp-soft-44.1.pcm --TCOutFile=dtc-soft-44.1.pcm "..\config\44.1 kHz\soft-44.1.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSOutFile=dxp-normal-44.1.pcm --MSOutFile=dmp-normal-44.1.pcm --TCOutFile=dtc-normal-44.1.pcm "..\config\44.1 kHz\normal-44.1.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSOutFile=dxp-strong-44.1.pcm --MSOutFile=dmp-strong-44.1.pcm --TCOutFile=dtc-strong-44.1.pcm "..\config\44.1 kHz\strong-44.1.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSOutFile=dxp-extreme-44.1.pcm --MSOutFile=dmp-extreme-44.1.pcm --TCOutFile=dtc-extreme-44.1.pcm "..\config\44.1 kHz\extreme-44.1.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSPointsFile="..\target\44.1 kHz\flat-44.1.txt" --PSOutFile=dxp-insane-44.1.pcm --MSOutFile=dmp-insane-44.1.pcm --TCOutFile=dtc-insane-44.1.pcm "..\config\44.1 kHz\insane-44.1.drc" rem 48.0 kHz drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSOutFile=dxp-erb-48.0.pcm --MSOutFile=dmp-erb-48.0.pcm --TCOutFile=dtc-erb-48.0.pcm "..\config\48.0 kHz\erb-48.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSOutFile=dxp-minimal-48.0.pcm --MSOutFile=dmp-minimal-48.0.pcm --TCOutFile=dtc-minimal-48.0.pcm "..\config\48.0 kHz\minimal-48.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSOutFile=dxp-soft-48.0.pcm --MSOutFile=dmp-soft-48.0.pcm --TCOutFile=dtc-soft-48.0.pcm "..\config\48.0 kHz\soft-48.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSOutFile=dxp-normal-48.0.pcm --MSOutFile=dmp-normal-48.0.pcm --TCOutFile=dtc-normal-48.0.pcm "..\config\48.0 kHz\normal-48.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSOutFile=dxp-strong-48.0.pcm --MSOutFile=dmp-strong-48.0.pcm --TCOutFile=dtc-strong-48.0.pcm "..\config\48.0 kHz\strong-48.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSOutFile=dxp-extreme-48.0.pcm --MSOutFile=dmp-extreme-48.0.pcm --TCOutFile=dtc-extreme-48.0.pcm "..\config\48.0 kHz\extreme-48.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSPointsFile="..\target\48.0 kHz\flat-48.0.txt" --PSOutFile=dxp-insane-48.0.pcm --MSOutFile=dmp-insane-48.0.pcm --TCOutFile=dtc-insane-48.0.pcm "..\config\48.0 kHz\insane-48.0.drc" rem 88.2 kHz drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSOutFile=dxp-erb-88.2.pcm --MSOutFile=dmp-erb-88.2.pcm --TCOutFile=dtc-erb-88.2.pcm "..\config\88.2 kHz\erb-88.2.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSOutFile=dxp-minimal-88.2.pcm --MSOutFile=dmp-minimal-88.2.pcm --TCOutFile=dtc-minimal-88.2.pcm "..\config\88.2 kHz\minimal-88.2.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSOutFile=dxp-soft-88.2.pcm --MSOutFile=dmp-soft-88.2.pcm --TCOutFile=dtc-soft-88.2.pcm "..\config\88.2 kHz\soft-88.2.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSOutFile=dxp-normal-88.2.pcm --MSOutFile=dmp-normal-88.2.pcm --TCOutFile=dtc-normal-88.2.pcm "..\config\88.2 kHz\normal-88.2.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSOutFile=dxp-strong-88.2.pcm --MSOutFile=dmp-strong-88.2.pcm --TCOutFile=dtc-strong-88.2.pcm "..\config\88.2 kHz\strong-88.2.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSOutFile=dxp-extreme-88.2.pcm --MSOutFile=dmp-extreme-88.2.pcm --TCOutFile=dtc-extreme-88.2.pcm "..\config\88.2 kHz\extreme-88.2.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSPointsFile="..\target\88.2 kHz\flat-88.2.txt" --PSOutFile=dxp-insane-88.2.pcm --MSOutFile=dmp-insane-88.2.pcm --TCOutFile=dtc-insane-88.2.pcm "..\config\88.2 kHz\insane-88.2.drc" rem 96.0 kHz drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSOutFile=dxp-erb-96.0.pcm --MSOutFile=dmp-erb-96.0.pcm --TCOutFile=dtc-erb-96.0.pcm "..\config\96.0 kHz\erb-96.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSOutFile=dxp-minimal-96.0.pcm --MSOutFile=dmp-minimal-96.0.pcm --TCOutFile=dtc-minimal-96.0.pcm "..\config\96.0 kHz\minimal-96.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSOutFile=dxp-soft-96.0.pcm --MSOutFile=dmp-soft-96.0.pcm --TCOutFile=dtc-soft-96.0.pcm "..\config\96.0 kHz\soft-96.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSOutFile=dxp-normal-96.0.pcm --MSOutFile=dmp-normal-96.0.pcm --TCOutFile=dtc-normal-96.0.pcm "..\config\96.0 kHz\normal-96.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSOutFile=dxp-strong-96.0.pcm --MSOutFile=dmp-strong-96.0.pcm --TCOutFile=dtc-strong-96.0.pcm "..\config\96.0 kHz\strong-96.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSOutFile=dxp-extreme-96.0.pcm --MSOutFile=dmp-extreme-96.0.pcm --TCOutFile=dtc-extreme-96.0.pcm "..\config\96.0 kHz\extreme-96.0.drc" drc --BCInFile=dirac.pcm --MCFilterType=M --MCPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSPointsFile="..\target\96.0 kHz\flat-96.0.txt" --PSOutFile=dxp-insane-96.0.pcm --MSOutFile=dmp-insane-96.0.pcm --TCOutFile=dtc-insane-96.0.pcm "..\config\96.0 kHz\insane-96.0.drc"drc-3.2.2/source/bwprefilt.h0000644000076400001450000000333313162156312014722 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Prefiltratura a bande di un segnale */ #ifndef BWPreFilt_h #define BWPreFilt_h /* Inclusioni */ #include "dsplib.h" #include "dspwind.h" /* Tipo di curva parametrica da utilizzare */ typedef enum { BWPProportional, BWPBilinear } BWPPrefilteringType; /* Calcolo potenza intera di un numero */ DLReal IntPow(DLReal X,unsigned int N); /* Prefiltratura a bande di un segnale */ void BWPreFilt(const DLReal * InImp, const int IBS, const int FBS, const int FilterLen, const int OctaveSplit, const DLReal WindowExponent, const int SampleFreq, const DLReal FilterBegin, const DLReal FilterEnd, const int WindowGap, DLReal * OutImp, const WindowType WType, const BWPPrefilteringType BWPType); #endif drc-3.2.2/source/glsweep.layout0000644000076400001450000000055413165107243015464 0ustar denisitadm drc-3.2.2/source/MLeaks/0000755000076400001450000000000013165107360013727 5ustar denisitadmdrc-3.2.2/source/MLeaks/_nvwa.h0000644000076400001450000000533212615050533015213 0ustar denisitadm// -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- // vim:tabstop=4:shiftwidth=4:expandtab: /* * Copyright (C) 2013-2015 Wu Yongwei * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute * it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. If you use this * software in a product, an acknowledgement in the product * documentation would be appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must * not be misrepresented as being the original software. * 3. This notice may not be removed or altered from any source * distribution. * * This file is part of Stones of Nvwa: * http://sourceforge.net/projects/nvwa * */ /** * @file _nvwa.h * * Common definitions for preprocessing. * * @date 2015-10-28 */ #ifndef NVWA_NVWA_H #define NVWA_NVWA_H /** * @namespace nvwa * Namespace of the nvwa project. Most functions and global variables * are defined in this namespace. */ #ifndef NVWA_USE_NAMESPACE #ifdef __cplusplus #define NVWA_USE_NAMESPACE 1 #else #define NVWA_USE_NAMESPACE 0 #endif // __cplusplus #endif // NVWA_USE_NAMESPACE #if NVWA_USE_NAMESPACE #define NVWA_NAMESPACE_BEGIN namespace nvwa { #define NVWA_NAMESPACE_END } #define NVWA nvwa #else // NVWA_USE_NAMESPACE #define NVWA_NAMESPACE_BEGIN #define NVWA_NAMESPACE_END #define NVWA #endif // NVWA_USE_NAMESPACE #ifndef NVWA_APPLE #if defined(__APPLE__) && defined(__MACH__) #define NVWA_APPLE 1 #else #define NVWA_APPLE 0 #endif #endif // NVWA_APPLE #ifndef NVWA_CYGWIN #if defined(__CYGWIN__) #define NVWA_CYGWIN 1 #else #define NVWA_CYGWIN 0 #endif #endif // NVWA_CYGWIN #ifndef NVWA_LINUX #if defined(__linux__) || defined(__linux) #define NVWA_LINUX 1 #else #define NVWA_LINUX 0 #endif #endif // NVWA_LINUX #ifndef NVWA_UNIX #if defined(__unix__) || defined(__unix) || NVWA_APPLE #define NVWA_UNIX 1 #else #define NVWA_UNIX 0 #endif #endif // NVWA_UNIX #ifndef NVWA_WIN32 #if defined(_WIN32) #define NVWA_WIN32 1 #else #define NVWA_WIN32 0 #endif #endif // NVWA_WIN32 #ifndef NVWA_WINDOWS #if NVWA_CYGWIN || NVWA_WIN32 #define NVWA_WINDOWS 1 #else #define NVWA_WINDOWS 0 #endif #endif // NVWA_WINDOWS #endif // NVWA_NVWA_H drc-3.2.2/source/MLeaks/debug_new.cpp0000644000076400001450000011012613000113247016360 0ustar denisitadm// -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- // vim:tabstop=4:shiftwidth=4:expandtab: /* * Copyright (C) 2004-2016 Wu Yongwei * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute * it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. If you use this * software in a product, an acknowledgement in the product * documentation would be appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must * not be misrepresented as being the original software. * 3. This notice may not be removed or altered from any source * distribution. * * This file is part of Stones of Nvwa: * http://sourceforge.net/projects/nvwa * */ /** * @file debug_new.cpp * * Implementation of debug versions of new and delete to check leakage. * * @date 2016-10-14 */ #include // std::bad_alloc/nothrow_t #include // assert #include // fprintf/stderr #include // abort #include // strcpy/strncpy/sprintf #include "_nvwa.h" // NVWA macros #if NVWA_UNIX #include // alloca #endif #if NVWA_WIN32 #include // alloca #endif #if NVWA_LINUX || NVWA_APPLE #include // backtrace #endif #if NVWA_WINDOWS #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include // CaptureStackBackTrace #endif #include "c++11.h" // _NOEXCEPT/_NULLPTR #include "fast_mutex.h" // nvwa::fast_mutex #include "static_assert.h" // STATIC_ASSERT #undef _DEBUG_NEW_EMULATE_MALLOC #undef _DEBUG_NEW_REDEFINE_NEW /** * Macro to indicate whether redefinition of \c new is wanted. Here it * is defined to \c 0 to disable the redefinition of \c new. */ #define _DEBUG_NEW_REDEFINE_NEW 0 #include "debug_new.h" #if !_FAST_MUTEX_CHECK_INITIALIZATION && !defined(_NOTHREADS) #error "_FAST_MUTEX_CHECK_INITIALIZATION not set: check_leaks may not work" #endif /** * @def _DEBUG_NEW_ALIGNMENT * * The alignment requirement of allocated memory blocks. It must be a * power of two. */ #ifndef _DEBUG_NEW_ALIGNMENT #define _DEBUG_NEW_ALIGNMENT 16 #endif /** * @def _DEBUG_NEW_CALLER_ADDRESS * * The expression to return the caller address. nvwa#print_position will * later on use this address to print the position information of memory * operation points. */ #ifndef _DEBUG_NEW_CALLER_ADDRESS #ifdef __GNUC__ #define _DEBUG_NEW_CALLER_ADDRESS __builtin_return_address(0) #else #define _DEBUG_NEW_CALLER_ADDRESS _NULLPTR #endif #endif /** * @def _DEBUG_NEW_ERROR_ACTION * * The action to take when an error occurs. The default behaviour is to * call \e abort, unless \c _DEBUG_NEW_ERROR_CRASH is defined, in which * case a segmentation fault will be triggered instead (which can be * useful on platforms like Windows that do not generate a core dump * when \e abort is called). */ #ifndef _DEBUG_NEW_ERROR_ACTION #ifndef _DEBUG_NEW_ERROR_CRASH #define _DEBUG_NEW_ERROR_ACTION abort() #else #define _DEBUG_NEW_ERROR_ACTION do { *((char*)0) = 0; abort(); } while (0) #endif #endif /** * @def _DEBUG_NEW_FILENAME_LEN * * The length of file name stored if greater than zero. If it is zero, * only a const char pointer will be stored. Currently the default * value is non-zero (thus to copy the file name) on non-Windows * platforms, because I once found that the exit leakage check could not * access the address of the file name on Linux (in my case, a core dump * occurred when check_leaks tried to access the file name in a shared * library after a \c SIGINT). This value makes the size of * new_ptr_list_t \c 64 on non-Windows 32-bit platforms (w/o stack * backtrace). */ #ifndef _DEBUG_NEW_FILENAME_LEN #if NVWA_WINDOWS #define _DEBUG_NEW_FILENAME_LEN 0 #else #define _DEBUG_NEW_FILENAME_LEN 44 #endif #endif /** * @def _DEBUG_NEW_PROGNAME * * The program (executable) name to be set at compile time. It is * better to assign the full program path to nvwa#new_progname in \e main * (at run time) than to use this (compile-time) macro, but this macro * serves well as a quick hack. Note also that double quotation marks * need to be used around the program name, i.e., one should specify a * command-line option like -D_DEBUG_NEW_PROGNAME=\\"a.out\" * in \e bash, or -D_DEBUG_NEW_PROGNAME=\\"a.exe\" in the * Windows command prompt. */ #ifndef _DEBUG_NEW_PROGNAME #define _DEBUG_NEW_PROGNAME _NULLPTR #endif /** * @def _DEBUG_NEW_REMEMBER_STACK_TRACE * * Macro to indicate whether stack traces of allocations should be * included in NVWA allocation information and be printed while leaks * are reported. Useful to pinpoint leaks caused by strdup and other * custom allocation functions. It is also very helpful in filtering * out false positives caused by internal STL/C runtime operations. It * is off by default because it is quite memory heavy. Set it to \c 1 * to make all allocations have stack trace attached, or set to \c 2 to * make only allocations that lack calling source code information (file * and line) have the stack trace attached. */ #ifndef _DEBUG_NEW_REMEMBER_STACK_TRACE #define _DEBUG_NEW_REMEMBER_STACK_TRACE 0 #endif /** * @def _DEBUG_NEW_STD_OPER_NEW * * Macro to indicate whether the standard-conformant behaviour of * operator new is wanted. It is on by default now, but * the user may set it to \c 0 to revert to the old behaviour. */ #ifndef _DEBUG_NEW_STD_OPER_NEW #define _DEBUG_NEW_STD_OPER_NEW 1 #endif /** * @def _DEBUG_NEW_TAILCHECK * * Macro to indicate whether a writing-past-end check will be performed. * Define it to a positive integer as the number of padding bytes at the * end of a memory block for checking. */ #ifndef _DEBUG_NEW_TAILCHECK #define _DEBUG_NEW_TAILCHECK 0 #endif /** * @def _DEBUG_NEW_TAILCHECK_CHAR * * Value of the padding bytes at the end of a memory block. */ #ifndef _DEBUG_NEW_TAILCHECK_CHAR #define _DEBUG_NEW_TAILCHECK_CHAR 0xCC #endif /** * @def _DEBUG_NEW_USE_ADDR2LINE * * Whether to use \e addr2line to convert a caller address to file/line * information. Defining it to a non-zero value will enable the * conversion (automatically done if GCC is detected). Defining it to * zero will disable the conversion. */ #ifndef _DEBUG_NEW_USE_ADDR2LINE #ifdef __GNUC__ #define _DEBUG_NEW_USE_ADDR2LINE 1 #else #define _DEBUG_NEW_USE_ADDR2LINE 0 #endif #endif #ifdef _MSC_VER #pragma warning(disable: 4074) // #pragma init_seg(compiler) used #pragma warning(disable: 4290) // C++ exception specification ignored #if _MSC_VER >= 1400 // Visual Studio 2005 or later #pragma warning(disable: 4996) // Use the `unsafe' strncpy #endif #pragma init_seg(compiler) #endif /** * Gets the aligned value of memory block size. */ #define ALIGN(s) \ (((s) + _DEBUG_NEW_ALIGNMENT - 1) & ~(_DEBUG_NEW_ALIGNMENT - 1)) NVWA_NAMESPACE_BEGIN /** * The platform memory alignment. The current value works well in * platforms I have tested: Windows XP, Windows 7 x64, and Mac OS X * Leopard. It may be smaller than the real alignment, but must be * bigger than \c sizeof(size_t) for it work. nvwa#debug_new_recorder * uses it to detect misaligned pointer returned by `new * NonPODType[size]'. */ const size_t PLATFORM_MEM_ALIGNMENT = sizeof(size_t) * 2; /** * Structure to store the position information where \c new occurs. */ struct new_ptr_list_t { new_ptr_list_t* next; ///< Pointer to the next memory block new_ptr_list_t* prev; ///< Pointer to the previous memory block size_t size; ///< Size of the memory block union { #if _DEBUG_NEW_FILENAME_LEN == 0 const char* file; ///< Pointer to the file name of the caller #else char file[_DEBUG_NEW_FILENAME_LEN]; ///< File name of the caller #endif void* addr; ///< Address of the caller to \e new }; unsigned line :31; ///< Line number of the caller; or \c 0 unsigned is_array:1; ///< Non-zero iff new[] is used #if _DEBUG_NEW_REMEMBER_STACK_TRACE void** stacktrace; ///< Pointer to stack trace information #endif unsigned magic; ///< Magic number for error detection }; /** * Definition of the constant magic number used for error detection. */ static const unsigned DEBUG_NEW_MAGIC = 0x4442474E; /** * The extra memory allocated by operator new. */ static const int ALIGNED_LIST_ITEM_SIZE = ALIGN(sizeof(new_ptr_list_t)); /** * List of all new'd pointers. */ static new_ptr_list_t new_ptr_list = { &new_ptr_list, &new_ptr_list, 0, { #if _DEBUG_NEW_FILENAME_LEN == 0 _NULLPTR #else "" #endif }, 0, 0, #if _DEBUG_NEW_REMEMBER_STACK_TRACE _NULLPTR, #endif DEBUG_NEW_MAGIC }; /** * The mutex guard to protect simultaneous access to the pointer list. */ static fast_mutex new_ptr_lock; /** * The mutex guard to protect simultaneous output to #new_output_fp. */ static fast_mutex new_output_lock; /** * Total memory allocated in bytes. */ static size_t total_mem_alloc = 0; /** * Flag to control whether nvwa#check_leaks will be automatically called * on program exit. */ bool new_autocheck_flag = true; /** * Flag to control whether verbose messages are output. */ bool new_verbose_flag = false; /** * Pointer to the output stream. The default output is \e stderr, and * one may change it to a user stream if needed (say, #new_verbose_flag * is \c true and there are a lot of (de)allocations). */ FILE* new_output_fp = stderr; /** * Pointer to the program name. Its initial value is the macro * #_DEBUG_NEW_PROGNAME. You should try to assign the program path to * it early in your application. Assigning argv[0] to it * in \e main is one way. If you use \e bash or \e ksh (or similar), * the following statement is probably what you want: * `new_progname = getenv("_");'. */ const char* new_progname = _DEBUG_NEW_PROGNAME; /** * Pointer to the callback used to print the stack backtrace in case of * a memory problem. A null value causes the default stack trace * printing routine to be used. */ stacktrace_print_callback_t stacktrace_print_callback = _NULLPTR; /** * Pointer to the callback used to filter out false positives from leak * reports. A null value means the lack of filtering. */ leak_whitelist_callback_t leak_whitelist_callback = _NULLPTR; #if _DEBUG_NEW_USE_ADDR2LINE /** * Tries printing the position information from an instruction address. * This is the version that uses \e addr2line. * * @param addr the instruction address to convert and print * @return \c true if the address is converted successfully (and * the result is printed); \c false if no useful * information is got (and nothing is printed) */ static bool print_position_from_addr(const void* addr) { static const void* last_addr = _NULLPTR; static char last_info[256] = ""; if (addr == last_addr) { if (last_info[0] == '\0') return false; fprintf(new_output_fp, "%s", last_info); return true; } if (new_progname) { #if NVWA_APPLE const char addr2line_cmd[] = "atos -o "; #else const char addr2line_cmd[] = "addr2line -e "; #endif #if NVWA_WINDOWS const int exeext_len = 4; #else const int exeext_len = 0; #endif #if NVWA_UNIX && !NVWA_CYGWIN const char ignore_err[] = " 2>/dev/null"; #elif NVWA_CYGWIN || \ (NVWA_WIN32 && defined(WINVER) && WINVER >= 0x0500) const char ignore_err[] = " 2>nul"; #else const char ignore_err[] = ""; #endif char* cmd = (char*)alloca(strlen(new_progname) + exeext_len + sizeof addr2line_cmd - 1 + sizeof ignore_err - 1 + sizeof(void*) * 2 + 4 /* SP + "0x" + null */); strcpy(cmd, addr2line_cmd); strcpy(cmd + sizeof addr2line_cmd - 1, new_progname); size_t len = strlen(cmd); #if NVWA_WINDOWS if (len <= 4 || (strcmp(cmd + len - 4, ".exe") != 0 && strcmp(cmd + len - 4, ".EXE") != 0)) { strcpy(cmd + len, ".exe"); len += 4; } #endif sprintf(cmd + len, " %p%s", addr, ignore_err); FILE* fp = popen(cmd, "r"); if (fp) { char buffer[sizeof last_info] = ""; len = 0; if (fgets(buffer, sizeof buffer, fp)) { len = strlen(buffer); if (buffer[len - 1] == '\n') buffer[--len] = '\0'; } int res = pclose(fp); // Display the file/line information only if the command // is executed successfully and the output points to a // valid position, but the result will be cached if only // the command is executed successfully. if (res == 0 && len > 0) { last_addr = addr; if (buffer[len - 1] == '0' && buffer[len - 2] == ':') last_info[0] = '\0'; else { fprintf(new_output_fp, "%s", buffer); strcpy(last_info, buffer); return true; } } } } return false; } #else /** * Tries printing the position information from an instruction address. * This is the stub version that does nothing at all. * * @return \c false always */ static bool print_position_from_addr(const void*) { return false; } #endif // _DEBUG_NEW_USE_ADDR2LINE /** * Prints the position information of a memory operation point. When \c * _DEBUG_NEW_USE_ADDR2LINE is defined to a non-zero value, this * function will try to convert a given caller address to file/line * information with \e addr2line. * * @param ptr source file name if \e line is non-zero; caller address * otherwise * @param line source line number if non-zero; indication that \e ptr * is the caller address otherwise */ static void print_position(const void* ptr, int line) { if (line != 0) // Is file/line information present? { fprintf(new_output_fp, "%s:%d", (const char*)ptr, line); } else if (ptr != _NULLPTR) // Is caller address present? { if (!print_position_from_addr(ptr)) // Fail to get source position? fprintf(new_output_fp, "%p", ptr); } else // No information is present { fprintf(new_output_fp, ""); } } #if _DEBUG_NEW_REMEMBER_STACK_TRACE /** * Prints the stack backtrace. * * When nvwa#stacktrace_print_callback is not null, it is used for * printing the stacktrace items. Default implementation of call stack * printing is very spartan—only stack frame pointers are * printed—but even that output is still useful. Just do address * lookup in LLDB etc. * * @param stacktrace pointer to the stack trace array */ static void print_stacktrace(void** stacktrace) { if (stacktrace_print_callback == _NULLPTR) { fprintf(new_output_fp, "Stack backtrace:\n"); for (size_t i = 0; stacktrace[i] != _NULLPTR; ++i) fprintf(new_output_fp, "%p\n", stacktrace[i]); } else { stacktrace_print_callback(new_output_fp, stacktrace); } } #endif /** * Checks whether a leak should be ignored. Its runtime performance * depends on the callback nvwa#leak_whitelist_callback. * * @param ptr pointer to a new_ptr_list_t struct * @return \c true if the leak should be whitelisted; \c false * otherwise */ static bool is_leak_whitelisted(new_ptr_list_t* ptr) { if (leak_whitelist_callback == _NULLPTR) return false; char const* file = ptr->line != 0 ? ptr->file : _NULLPTR; int line = ptr->line; void* addr = ptr->line == 0 ? ptr->addr : _NULLPTR; #if _DEBUG_NEW_REMEMBER_STACK_TRACE void** stacktrace = ptr->stacktrace; #else void** stacktrace = _NULLPTR; #endif return leak_whitelist_callback(file, line, addr, stacktrace); } #if _DEBUG_NEW_TAILCHECK /** * Checks whether the padding bytes at the end of a memory block is * tampered with. * * @param ptr pointer to a new_ptr_list_t struct * @return \c true if the padding bytes are untouched; \c false * otherwise */ static bool check_tail(new_ptr_list_t* ptr) { const unsigned char* const tail_ptr = (unsigned char*)ptr + ALIGNED_LIST_ITEM_SIZE + ptr->size; for (int i = 0; i < _DEBUG_NEW_TAILCHECK; ++i) if (tail_ptr[i] != _DEBUG_NEW_TAILCHECK_CHAR) return false; return true; } #endif /** * Allocates memory and initializes control data. * * @param size size of the required memory block * @param file null-terminated string of the file name * @param line line number * @param is_array boolean value whether this is an array operation * @return pointer to the user-requested memory area; null if * memory allocation is not successful */ static void* alloc_mem(size_t size, const char* file, int line, bool is_array) { assert(line >= 0); #if _DEBUG_NEW_TYPE == 1 STATIC_ASSERT(_DEBUG_NEW_ALIGNMENT >= PLATFORM_MEM_ALIGNMENT, Alignment_too_small); #endif STATIC_ASSERT((_DEBUG_NEW_ALIGNMENT & (_DEBUG_NEW_ALIGNMENT - 1)) == 0, Alignment_must_be_power_of_two); STATIC_ASSERT(_DEBUG_NEW_TAILCHECK >= 0, Invalid_tail_check_length); size_t s = size + ALIGNED_LIST_ITEM_SIZE + _DEBUG_NEW_TAILCHECK; new_ptr_list_t* ptr = (new_ptr_list_t*)malloc(s); if (ptr == _NULLPTR) { #if _DEBUG_NEW_STD_OPER_NEW return _NULLPTR; #else fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "Out of memory when allocating %lu bytes\n", (unsigned long)size); fflush(new_output_fp); _DEBUG_NEW_ERROR_ACTION; #endif } void* usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE; #if _DEBUG_NEW_FILENAME_LEN == 0 ptr->file = file; #else if (line) strncpy(ptr->file, file, _DEBUG_NEW_FILENAME_LEN - 1) [_DEBUG_NEW_FILENAME_LEN - 1] = '\0'; else ptr->addr = (void*)file; #endif ptr->line = line; #if _DEBUG_NEW_REMEMBER_STACK_TRACE ptr->stacktrace = _NULLPTR; #if _DEBUG_NEW_REMEMBER_STACK_TRACE == 2 if (line == 0) #endif { void* buffer [255]; size_t buffer_length = sizeof(buffer) / sizeof(*buffer); #if NVWA_UNIX int stacktrace_length = backtrace(buffer, int(buffer_length)); #endif #if NVWA_WINDOWS USHORT stacktrace_length = CaptureStackBackTrace( 0, DWORD(buffer_length), buffer, _NULLPTR); #endif size_t stacktrace_size = stacktrace_length * sizeof(void*); ptr->stacktrace = (void**)malloc(stacktrace_size + sizeof(void*)); if (ptr->stacktrace != _NULLPTR) { memcpy(ptr->stacktrace, buffer, stacktrace_size); ptr->stacktrace[stacktrace_length] = _NULLPTR; } } #endif ptr->is_array = is_array; ptr->size = size; ptr->magic = DEBUG_NEW_MAGIC; { fast_mutex_autolock lock(new_ptr_lock); ptr->prev = new_ptr_list.prev; ptr->next = &new_ptr_list; new_ptr_list.prev->next = ptr; new_ptr_list.prev = ptr; } #if _DEBUG_NEW_TAILCHECK memset((char*)usr_ptr + size, _DEBUG_NEW_TAILCHECK_CHAR, _DEBUG_NEW_TAILCHECK); #endif if (new_verbose_flag) { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "new%s: allocated %p (size %lu, ", is_array ? "[]" : "", usr_ptr, (unsigned long)size); if (line != 0) print_position(ptr->file, ptr->line); else print_position(ptr->addr, ptr->line); fprintf(new_output_fp, ")\n"); } total_mem_alloc += size; return usr_ptr; } /** * Frees memory and adjusts pointers. * * @param usr_ptr pointer to the previously allocated memory * @param addr pointer to the caller * @param is_array flag indicating whether it is invoked by a * delete[] call */ static void free_pointer(void* usr_ptr, void* addr, bool is_array) { if (usr_ptr == _NULLPTR) return; new_ptr_list_t* ptr = (new_ptr_list_t*)((char*)usr_ptr - ALIGNED_LIST_ITEM_SIZE); if (ptr->magic != DEBUG_NEW_MAGIC) { { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "delete%s: invalid pointer %p (", is_array ? "[]" : "", usr_ptr); print_position(addr, 0); fprintf(new_output_fp, ")\n"); } check_mem_corruption(); fflush(new_output_fp); _DEBUG_NEW_ERROR_ACTION; } if (is_array != ptr->is_array) { const char* msg; if (is_array) msg = "delete[] after new"; else msg = "delete after new[]"; fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "%s: pointer %p (size %lu)\n\tat ", msg, (char*)ptr + ALIGNED_LIST_ITEM_SIZE, (unsigned long)ptr->size); print_position(addr, 0); fprintf(new_output_fp, "\n\toriginally allocated at "); if (ptr->line != 0) print_position(ptr->file, ptr->line); else print_position(ptr->addr, ptr->line); fprintf(new_output_fp, "\n"); fflush(new_output_fp); _DEBUG_NEW_ERROR_ACTION; } #if _DEBUG_NEW_TAILCHECK if (!check_tail(ptr)) { check_mem_corruption(); fflush(new_output_fp); _DEBUG_NEW_ERROR_ACTION; } #endif { fast_mutex_autolock lock(new_ptr_lock); total_mem_alloc -= ptr->size; ptr->magic = 0; ptr->prev->next = ptr->next; ptr->next->prev = ptr->prev; } if (new_verbose_flag) { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "delete%s: freed %p (size %lu, %lu bytes still allocated)\n", is_array ? "[]" : "", (char*)ptr + ALIGNED_LIST_ITEM_SIZE, (unsigned long)ptr->size, (unsigned long)total_mem_alloc); } #if _DEBUG_NEW_REMEMBER_STACK_TRACE free(ptr->stacktrace); #endif free(ptr); return; } /** * Checks for memory leaks. * * @return zero if no leakage is found; the number of leaks otherwise */ int check_leaks() { int leak_cnt = 0; int whitelisted_leak_cnt = 0; fast_mutex_autolock lock_ptr(new_ptr_lock); fast_mutex_autolock lock_output(new_output_lock); new_ptr_list_t* ptr = new_ptr_list.next; while (ptr != &new_ptr_list) { const char* const usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE; if (ptr->magic != DEBUG_NEW_MAGIC) { fprintf(new_output_fp, "warning: heap data corrupt near %p\n", usr_ptr); } #if _DEBUG_NEW_TAILCHECK if (!check_tail(ptr)) { fprintf(new_output_fp, "warning: overwritten past end of object at %p\n", usr_ptr); } #endif if (is_leak_whitelisted(ptr)) { ++whitelisted_leak_cnt; } else { fprintf(new_output_fp, "Leaked object at %p (size %lu, ", usr_ptr, (unsigned long)ptr->size); if (ptr->line != 0) print_position(ptr->file, ptr->line); else print_position(ptr->addr, ptr->line); fprintf(new_output_fp, ")\n"); #if _DEBUG_NEW_REMEMBER_STACK_TRACE if (ptr->stacktrace != _NULLPTR) print_stacktrace(ptr->stacktrace); #endif } ptr = ptr->next; ++leak_cnt; } if (new_verbose_flag || leak_cnt) { if (whitelisted_leak_cnt > 0) { fprintf(new_output_fp, "*** %d leaks found (%d whitelisted)\n", leak_cnt, whitelisted_leak_cnt); } else { fprintf(new_output_fp, "*** %d leaks found\n", leak_cnt); } } return leak_cnt; } /** * Checks for heap corruption. * * @return zero if no problem is found; the number of found memory * corruptions otherwise */ int check_mem_corruption() { int corrupt_cnt = 0; fast_mutex_autolock lock_ptr(new_ptr_lock); fast_mutex_autolock lock_output(new_output_lock); fprintf(new_output_fp, "*** Checking for memory corruption: START\n"); for (new_ptr_list_t* ptr = new_ptr_list.next; ptr != &new_ptr_list; ptr = ptr->next) { const char* const usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE; if (ptr->magic == DEBUG_NEW_MAGIC #if _DEBUG_NEW_TAILCHECK && check_tail(ptr) #endif ) continue; #if _DEBUG_NEW_TAILCHECK if (ptr->magic != DEBUG_NEW_MAGIC) { #endif fprintf(new_output_fp, "Heap data corrupt near %p (size %lu, ", usr_ptr, (unsigned long)ptr->size); #if _DEBUG_NEW_TAILCHECK } else { fprintf(new_output_fp, "Overwritten past end of object at %p (size %lu, ", usr_ptr, (unsigned long)ptr->size); } #endif if (ptr->line != 0) print_position(ptr->file, ptr->line); else print_position(ptr->addr, ptr->line); fprintf(new_output_fp, ")\n"); #if _DEBUG_NEW_REMEMBER_STACK_TRACE if (ptr->stacktrace != _NULLPTR) print_stacktrace(ptr->stacktrace); #endif ++corrupt_cnt; } fprintf(new_output_fp, "*** Checking for memory corruption: %d FOUND\n", corrupt_cnt); return corrupt_cnt; } /** * Processes the allocated memory and inserts file/line informatin. * It will only be done when it can ensure the memory is allocated by * one of our operator new variants. * * @param usr_ptr pointer returned by a new-expression */ void debug_new_recorder::_M_process(void* usr_ptr) { if (usr_ptr == _NULLPTR) return; // In an expression `new NonPODType[size]', the pointer returned is // not the pointer returned by operator new[], but offset by size_t // to leave room for the size. It needs to be compensated here. size_t offset = (char*)usr_ptr - (char*)_NULLPTR; if (offset % PLATFORM_MEM_ALIGNMENT != 0) { offset -= sizeof(size_t); if (offset % PLATFORM_MEM_ALIGNMENT != 0) { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "warning: memory unaligned; skipping processing (%s:%d)\n", _M_file, _M_line); return; } usr_ptr = (char*)usr_ptr - sizeof(size_t); } new_ptr_list_t* ptr = (new_ptr_list_t*)((char*)usr_ptr - ALIGNED_LIST_ITEM_SIZE); if (ptr->magic != DEBUG_NEW_MAGIC || ptr->line != 0) { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "warning: debug_new used with placement new (%s:%d)\n", _M_file, _M_line); return; } if (new_verbose_flag) { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "info: pointer %p allocated from %s:%d\n", usr_ptr, _M_file, _M_line); } #if _DEBUG_NEW_FILENAME_LEN == 0 ptr->file = _M_file; #else strncpy(ptr->file, _M_file, _DEBUG_NEW_FILENAME_LEN - 1) [_DEBUG_NEW_FILENAME_LEN - 1] = '\0'; #endif ptr->line = _M_line; #if _DEBUG_NEW_REMEMBER_STACK_TRACE == 2 free(ptr->stacktrace); ptr->stacktrace = _NULLPTR; #endif } /** * Count of source files that use debug_new. */ int debug_new_counter::_S_count = 0; /** * Constructor to increment the count. */ debug_new_counter::debug_new_counter() { ++_S_count; } /** * Destructor to decrement the count. When the count is zero, * nvwa#check_leaks will be called. */ debug_new_counter::~debug_new_counter() { if (--_S_count == 0 && new_autocheck_flag) if (check_leaks()) { new_verbose_flag = true; #if defined(__GNUC__) && __GNUC__ == 3 if (!getenv("GLIBCPP_FORCE_NEW") && !getenv("GLIBCXX_FORCE_NEW")) fprintf(new_output_fp, "*** WARNING: GCC 3 is detected, please make sure the environment\n" " variable GLIBCPP_FORCE_NEW (GCC 3.2 and 3.3) or GLIBCXX_FORCE_NEW\n" " (GCC 3.4) is defined. Check the README file for details.\n"); #endif } } NVWA_NAMESPACE_END #if NVWA_USE_NAMESPACE using namespace nvwa; #endif // NVWA_USE_NAMESPACE /** * Allocates memory with file/line information. * * @param size size of the required memory block * @param file null-terminated string of the file name * @param line line number * @return pointer to the memory allocated; or null if memory is * insufficient (#_DEBUG_NEW_STD_OPER_NEW is 0) * @throw bad_alloc memory is insufficient (#_DEBUG_NEW_STD_OPER_NEW is 1) */ void* operator new(size_t size, const char* file, int line) { void* ptr = alloc_mem(size, file, line, false); #if _DEBUG_NEW_STD_OPER_NEW if (ptr) return ptr; else throw std::bad_alloc(); #else return ptr; #endif } /** * Allocates array memory with file/line information. * * @param size size of the required memory block * @param file null-terminated string of the file name * @param line line number * @return pointer to the memory allocated; or null if memory is * insufficient (#_DEBUG_NEW_STD_OPER_NEW is 0) * @throw bad_alloc memory is insufficient (#_DEBUG_NEW_STD_OPER_NEW is 1) */ void* operator new[](size_t size, const char* file, int line) { void* ptr = alloc_mem(size, file, line, true); #if _DEBUG_NEW_STD_OPER_NEW if (ptr) return ptr; else throw std::bad_alloc(); #else return ptr; #endif } /** * Allocates memory without file/line information. * * @param size size of the required memory block * @return pointer to the memory allocated; or null if memory is * insufficient (#_DEBUG_NEW_STD_OPER_NEW is 0) * @throw bad_alloc memory is insufficient (#_DEBUG_NEW_STD_OPER_NEW is 1) */ void* operator new(size_t size) throw(std::bad_alloc) { return operator new(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0); } /** * Allocates array memory without file/line information. * * @param size size of the required memory block * @return pointer to the memory allocated; or null if memory is * insufficient (#_DEBUG_NEW_STD_OPER_NEW is 0) * @throw bad_alloc memory is insufficient (#_DEBUG_NEW_STD_OPER_NEW is 1) */ void* operator new[](size_t size) throw(std::bad_alloc) { return operator new[](size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0); } /** * Allocates memory with no-throw guarantee. * * @param size size of the required memory block * @return pointer to the memory allocated; or null if memory is * insufficient */ void* operator new(size_t size, const std::nothrow_t&) _NOEXCEPT { return alloc_mem(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0, false); } /** * Allocates array memory with no-throw guarantee. * * @param size size of the required memory block * @return pointer to the memory allocated; or null if memory is * insufficient */ void* operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT { return alloc_mem(size, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0, true); } /** * Deallocates memory. * * @param ptr pointer to the previously allocated memory */ void operator delete(void* ptr) _NOEXCEPT { free_pointer(ptr, _DEBUG_NEW_CALLER_ADDRESS, false); } /** * Deallocates array memory. * * @param ptr pointer to the previously allocated memory */ void operator delete[](void* ptr) _NOEXCEPT { free_pointer(ptr, _DEBUG_NEW_CALLER_ADDRESS, true); } #if __cplusplus >= 201402L // GCC under C++14 wants these definitions void operator delete(void* ptr, size_t) _NOEXCEPT { free_pointer(ptr, _DEBUG_NEW_CALLER_ADDRESS, false); } void operator delete[](void* ptr, size_t) _NOEXCEPT { free_pointer(ptr, _DEBUG_NEW_CALLER_ADDRESS, true); } #endif /** * Placement deallocation function. For details, please check Section * 5.3.4 of the C++ 1998 or 2011 Standard. * * @param ptr pointer to the previously allocated memory * @param file null-terminated string of the file name * @param line line number * * @see http://www.csci.csusb.edu/dick/c++std/cd2/expr.html#expr.new * @see http://wyw.dcweb.cn/leakage.htm */ void operator delete(void* ptr, const char* file, int line) _NOEXCEPT { if (new_verbose_flag) { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "info: exception thrown on initializing object at %p (", ptr); print_position(file, line); fprintf(new_output_fp, ")\n"); } operator delete(ptr); } /** * Placement deallocation function. For details, please check Section * 5.3.4 of the C++ 1998 or 2011 Standard. * * @param ptr pointer to the previously allocated memory * @param file null-terminated string of the file name * @param line line number */ void operator delete[](void* ptr, const char* file, int line) _NOEXCEPT { if (new_verbose_flag) { fast_mutex_autolock lock(new_output_lock); fprintf(new_output_fp, "info: exception thrown on initializing objects at %p (", ptr); print_position(file, line); fprintf(new_output_fp, ")\n"); } operator delete[](ptr); } /** * Placement deallocation function. For details, please check Section * 5.3.4 of the C++ 1998 or 2011 Standard. * * @param ptr pointer to the previously allocated memory */ void operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT { operator delete(ptr, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0); } /** * Placement deallocation function. For details, please check Section * 5.3.4 of the C++ 1998 or 2011 Standard. * * @param ptr pointer to the previously allocated memory */ void operator delete[](void* ptr, const std::nothrow_t&) _NOEXCEPT { operator delete[](ptr, (char*)_DEBUG_NEW_CALLER_ADDRESS, 0); } // This is to make Doxygen happy #undef _DEBUG_NEW_REMEMBER_STACK_TRACE #define _DEBUG_NEW_REMEMBER_STACK_TRACE 0 drc-3.2.2/source/MLeaks/LICENCE0000644000076400001450000000161213067063424014717 0ustar denisitadmCopyright (C) 2004-2017 Wu Yongwei This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgement in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. drc-3.2.2/source/MLeaks/c++11.h0000644000076400001450000002324513070424152014614 0ustar denisitadm// -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- // vim:tabstop=4:shiftwidth=4:expandtab: /* * Copyright (C) 2013-2017 Wu Yongwei * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute * it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. If you use this * software in a product, an acknowledgement in the product * documentation would be appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must * not be misrepresented as being the original software. * 3. This notice may not be removed or altered from any source * distribution. * * This file is part of Stones of Nvwa: * http://sourceforge.net/projects/nvwa * */ /** * @file c++11.h * * C++11 feature detection macros and workarounds. * * @date 2017-04-03 */ #ifndef NVWA_CXX11_H #define NVWA_CXX11_H // Only Clang provides these macros; they need to be defined as follows // to get a valid expression in preprocessing by other compilers. #ifndef __has_extension #define __has_extension(x) 0 #endif #ifndef __has_feature #define __has_feature(x) 0 #endif #ifndef __has_include #define __has_include(x) 0 #endif // Detect whether C++11 mode is on (for GCC and Clang). MSVC does not // have a special C++11 mode, so it is always on for Visual C++ 2010 and // later. #if __cplusplus >= 201103L || \ defined(__GXX_EXPERIMENTAL_CXX0X__) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) #define NVWA_CXX11_MODE 1 #else #define NVWA_CXX11_MODE 0 #endif /* Feature checks */ #if !defined(HAVE_CXX11_ATOMIC) #if NVWA_CXX11_MODE && \ ((__has_include() && !defined(__MINGW32__)) || \ (defined(_MSC_VER) && _MSC_VER >= 1700) || \ (((defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 405) || \ defined(__clang__)) && \ (!defined(__MINGW32__) || defined(_POSIX_THREADS)))) // Note: MinGW GCC, unless built with POSIX threads (as in // MinGW-builds), does not support atomics as of 4.8. #define HAVE_CXX11_ATOMIC 1 #else #define HAVE_CXX11_ATOMIC 0 #endif #endif #if !defined(HAVE_CXX11_AUTO_TYPE) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_auto_type) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 404)) #define HAVE_CXX11_AUTO_TYPE 1 #else #define HAVE_CXX11_AUTO_TYPE 0 #endif #endif #if !defined(HAVE_CXX11_DELETED_FUNCTION) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_deleted_functions) || \ (defined(_MSC_VER) && _MSC_VER >= 1800) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 404)) #define HAVE_CXX11_DELETED_FUNCTION 1 #else #define HAVE_CXX11_DELETED_FUNCTION 0 #endif #endif #if !defined(HAVE_CXX11_EXPLICIT_CONVERSION) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_explicit_conversions) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 405)) #define HAVE_CXX11_EXPLICIT_CONVERSION 1 #else #define HAVE_CXX11_EXPLICIT_CONVERSION 0 #endif #endif #if !defined(HAVE_CXX11_FINAL) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_override_control) || \ (defined(_MSC_VER) && _MSC_VER >= 1700) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 407)) #define HAVE_CXX11_FINAL 1 #else #define HAVE_CXX11_FINAL 0 #endif #endif #if !defined(HAVE_CXX11_FUTURE) #if NVWA_CXX11_MODE && \ ((__has_include() && !defined(__MINGW32__)) || \ (defined(_MSC_VER) && _MSC_VER >= 1700) || \ (((defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 405) || \ defined(__clang__)) && \ (!defined(__MINGW32__) || defined(_POSIX_THREADS)))) // Note: MinGW GCC, unless built with POSIX threads (as in // MinGW-builds), does not support futures as of 4.8. #define HAVE_CXX11_FUTURE 1 #else #define HAVE_CXX11_FUTURE 0 #endif #endif #if !defined(HAVE_CXX11_GENERALIZED_INITIALIZER) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_generalized_initializers) || \ (defined(_MSC_VER) && _MSC_VER >= 1800) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 404)) #define HAVE_CXX11_GENERALIZED_INITIALIZER 1 #else #define HAVE_CXX11_GENERALIZED_INITIALIZER 0 #endif #endif #if !defined(HAVE_CXX11_LAMBDA) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_lambdas) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 405)) #define HAVE_CXX11_LAMBDA 1 #else #define HAVE_CXX11_LAMBDA 0 #endif #endif #if !defined(HAVE_CXX11_MUTEX) #if NVWA_CXX11_MODE && \ ((__has_include() && !defined(__MINGW32__)) || \ (defined(_MSC_VER) && _MSC_VER >= 1700) || \ (((defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \ defined(__clang__)) && \ (!defined(__MINGW32__) || defined(_POSIX_THREADS)))) // Note: MinGW GCC, unless built with POSIX threads (as in // MinGW-builds), does not support std::mutex as of 4.8. #define HAVE_CXX11_MUTEX 1 #else #define HAVE_CXX11_MUTEX 0 #endif #endif #if !defined(HAVE_CXX11_NOEXCEPT) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_noexcept) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406)) #define HAVE_CXX11_NOEXCEPT 1 #else #define HAVE_CXX11_NOEXCEPT 0 #endif #endif #if !defined(HAVE_CXX11_NULLPTR) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_nullptr) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406)) #define HAVE_CXX11_NULLPTR 1 #else #define HAVE_CXX11_NULLPTR 0 #endif #endif #if !defined(HAVE_CXX11_OVERRIDE) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_override_control) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 407)) #define HAVE_CXX11_OVERRIDE 1 #else #define HAVE_CXX11_OVERRIDE 0 #endif #endif #if !defined(HAVE_CXX11_RANGE_FOR) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_range_for) || \ (defined(_MSC_VER) && _MSC_VER >= 1700) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 406)) #define HAVE_CXX11_RANGE_FOR 1 #else #define HAVE_CXX11_RANGE_FOR 0 #endif #endif #if !defined(HAVE_CXX11_RVALUE_REFERENCE) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_rvalue_references) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 405)) #define HAVE_CXX11_RVALUE_REFERENCE 1 #else #define HAVE_CXX11_RVALUE_REFERENCE 0 #endif #endif #if !defined(HAVE_CXX11_STATIC_ASSERT) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_static_assert) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 403)) #define HAVE_CXX11_STATIC_ASSERT 1 #else #define HAVE_CXX11_STATIC_ASSERT 0 #endif #endif #if !defined(HAVE_CXX11_THREAD) #if NVWA_CXX11_MODE && \ ((__has_include() && !defined(__MINGW32__)) || \ (defined(_MSC_VER) && _MSC_VER >= 1700) || \ (((defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 404) || \ defined(__clang__)) && \ (!defined(__MINGW32__) || defined(_POSIX_THREADS)))) // Note: MinGW GCC, unless built with POSIX threads (as in // MinGW-builds), does not support std::thread as of 4.8. #define HAVE_CXX11_THREAD 1 #else #define HAVE_CXX11_THREAD 0 #endif #endif #if !defined(HAVE_CXX11_THREAD_LOCAL) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_thread_local) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 408)) #define HAVE_CXX11_THREAD_LOCAL 1 #else #define HAVE_CXX11_THREAD_LOCAL 0 #endif #endif #if !defined(HAVE_CXX11_TYPE_TRAITS) #if NVWA_CXX11_MODE && \ (__has_include() || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 403)) #define HAVE_CXX11_TYPE_TRAITS 1 #else #define HAVE_CXX11_TYPE_TRAITS 0 #endif #endif #if !defined(HAVE_CXX11_UNICODE_LITERAL) #if NVWA_CXX11_MODE && \ (__has_feature(cxx_unicode_literals) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) || \ (defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ >= 405)) #define HAVE_CXX11_UNICODE_LITERAL 1 #else #define HAVE_CXX11_UNICODE_LITERAL 0 #endif #endif /* Workarounds */ #if HAVE_CXX11_DELETED_FUNCTION #define _DELETED = delete #else #define _DELETED #endif #if HAVE_CXX11_FINAL #define _FINAL final #else #define _FINAL #endif #if HAVE_CXX11_OVERRIDE #define _OVERRIDE override #else #define _OVERRIDE #endif #if HAVE_CXX11_NOEXCEPT #define _NOEXCEPT noexcept #define _NOEXCEPT_(x) noexcept(x) #else #ifdef _MSC_VER #define _NOEXCEPT throw () #else #define _NOEXCEPT throw() #endif #define _NOEXCEPT_(x) #endif #if HAVE_CXX11_NULLPTR #define _NULLPTR nullptr #else #define _NULLPTR NULL #endif #if HAVE_CXX11_THREAD_LOCAL #define _THREAD_LOCAL thread_local #else #ifdef _MSC_VER #define _THREAD_LOCAL __declspec(thread) #else #define _THREAD_LOCAL __thread #endif #endif #endif // NVWA_CXX11_H drc-3.2.2/source/MLeaks/static_assert.h0000644000076400001450000000345512212607123016751 0ustar denisitadm// -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- // vim:tabstop=4:shiftwidth=4:expandtab: /* * Copyright (C) 2004-2013 Wu Yongwei * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute * it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. If you use this * software in a product, an acknowledgement in the product * documentation would be appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must * not be misrepresented as being the original software. * 3. This notice may not be removed or altered from any source * distribution. * * This file is part of Stones of Nvwa: * http://sourceforge.net/projects/nvwa * */ /** * @file static_assert.h * * Template class to check validity duing compile time (adapted from Loki). * * @date 2013-09-07 */ #ifndef STATIC_ASSERT #include "c++11.h" #if HAVE_CXX11_STATIC_ASSERT #define STATIC_ASSERT(_Expr, _Msg) static_assert(_Expr, #_Msg) #else namespace nvwa { template struct compile_time_error; template <> struct compile_time_error {}; #define STATIC_ASSERT(_Expr, _Msg) \ { \ nvwa::compile_time_error<((_Expr) != 0)> ERROR_##_Msg; \ (void)ERROR_##_Msg; \ } } #endif // HAVE_CXX11_STATIC_ASSERT #endif // STATIC_ASSERT drc-3.2.2/source/MLeaks/fast_mutex.h0000644000076400001450000003175412615050550016266 0ustar denisitadm// -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- // vim:tabstop=4:shiftwidth=4:expandtab: /* * Copyright (C) 2004-2015 Wu Yongwei * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute * it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. If you use this * software in a product, an acknowledgement in the product * documentation would be appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must * not be misrepresented as being the original software. * 3. This notice may not be removed or altered from any source * distribution. * * This file is part of Stones of Nvwa: * http://sourceforge.net/projects/nvwa * */ /** * @file fast_mutex.h * * A fast mutex implementation for POSIX, Win32, and modern C++. * * @date 2015-05-19 */ #ifndef NVWA_FAST_MUTEX_H #define NVWA_FAST_MUTEX_H #include "_nvwa.h" // NVWA_NAMESPACE_* #include "c++11.h" // HAVE_CXX11_MUTEX # if !defined(_NOTHREADS) # if !defined(NVWA_USE_CXX11_MUTEX) && HAVE_CXX11_MUTEX != 0 && \ !defined(_WIN32THREADS) && !defined(NVWA_WIN32THREADS) && \ !defined(NVWA_PTHREADS) && !defined(NVWA_NOTHREADS) && \ defined(_WIN32) && defined(_MT) && \ (!defined(_MSC_VER) || defined(_DLL)) // Prefer using std::mutex on Windows to avoid the namespace // pollution caused by . However, MSVC has a re-entry // issue with its std::mutex implementation, and std::mutex should // not be used unless /MD or /MDd is used. For more information, // check out: // // https://connect.microsoft.com/VisualStudio/feedback/details/776596/std-mutex-not-a-constexpr-with-mtd-compiler-flag // http://stackoverflow.com/questions/14319344/stdmutex-lock-hangs-when-overriding-the-new-operator // # define NVWA_USE_CXX11_MUTEX 1 # endif # if !defined(_WIN32THREADS) && \ (defined(_WIN32) && defined(_MT)) // Automatically use _WIN32THREADS when specifying -MT/-MD in MSVC, // or -mthreads in MinGW GCC. # define _WIN32THREADS # elif !defined(_PTHREADS) && \ defined(_REENTRANT) // Automatically use _PTHREADS when specifying -pthread in GCC or Clang. # define _PTHREADS # endif # endif # ifndef NVWA_USE_CXX11_MUTEX # if HAVE_CXX11_MUTEX != 0 && \ !defined(_NOTHREADS) && !defined(NVWA_NOTHREADS) && \ !defined(_PTHREADS) && !defined(NVWA_PTHREADS) && \ !defined(_WIN32THREADS) && !defined(NVWA_WIN32THREADS) # define NVWA_USE_CXX11_MUTEX 1 # else # define NVWA_USE_CXX11_MUTEX 0 # endif # endif # if !defined(_PTHREADS) && !defined(_WIN32THREADS) && \ !defined(_NOTHREADS) && NVWA_USE_CXX11_MUTEX == 0 # define _NOTHREADS # endif # if defined(_NOTHREADS) # if defined(_PTHREADS) || defined(_WIN32THREADS) || \ NVWA_USE_CXX11_MUTEX != 0 # undef _NOTHREADS # error "Cannot define multi-threaded mode with -D_NOTHREADS" # endif # endif # if defined(__MINGW32__) && defined(_WIN32THREADS) && !defined(_MT) # error "Be sure to specify -mthreads with -D_WIN32THREADS" # endif // With all the heuristics above, things may still go wrong, maybe even // due to a specific inclusion order. So they may be overridden by // manually defining the NVWA_* macros below. # if NVWA_USE_CXX11_MUTEX == 0 && \ !defined(NVWA_WIN32THREADS) && \ !defined(NVWA_PTHREADS) && \ !defined(NVWA_NOTHREADS) // _WIN32THREADS takes precedence, as some C++ libraries have _PTHREADS // defined even on Win32 platforms. # if defined(_WIN32THREADS) # define NVWA_WIN32THREADS # elif defined(_PTHREADS) # define NVWA_PTHREADS # else # define NVWA_NOTHREADS # endif # endif # ifndef _FAST_MUTEX_CHECK_INITIALIZATION /** * Macro to control whether to check for initialization status for each * lock/unlock operation. Defining it to a non-zero value will enable * the check, so that the construction/destruction of a static object * using a static fast_mutex not yet constructed or already destroyed * will work (with lock/unlock operations ignored). Defining it to zero * will disable to check. */ # define _FAST_MUTEX_CHECK_INITIALIZATION 1 # endif # ifdef _DEBUG # include # include /** Macro for fast_mutex assertions. Real version (for debug mode). */ # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \ if (!(_Expr)) { \ fprintf(stderr, "fast_mutex::%s\n", _Msg); \ abort(); \ } # else /** Macro for fast_mutex assertions. Fake version (for release mode). */ # define _FAST_MUTEX_ASSERT(_Expr, _Msg) \ ((void)0) # endif # if NVWA_USE_CXX11_MUTEX != 0 # include NVWA_NAMESPACE_BEGIN /** * Macro alias to `volatile' semantics. Here it is truly volatile since * it is in a multi-threaded (C++11) environment. */ # define __VOLATILE volatile /** * Class for non-reentrant fast mutexes. This is the implementation * using the C++11 mutex. */ class fast_mutex { std::mutex _M_mtx_impl; # if _FAST_MUTEX_CHECK_INITIALIZATION bool _M_initialized; # endif # ifdef _DEBUG bool _M_locked; # endif public: fast_mutex() # ifdef _DEBUG : _M_locked(false) # endif { # if _FAST_MUTEX_CHECK_INITIALIZATION _M_initialized = true; # endif } ~fast_mutex() { _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked"); # if _FAST_MUTEX_CHECK_INITIALIZATION _M_initialized = false; # endif } void lock() { # if _FAST_MUTEX_CHECK_INITIALIZATION if (!_M_initialized) return; # endif _M_mtx_impl.lock(); # ifdef _DEBUG _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked"); _M_locked = true; # endif } void unlock() { # if _FAST_MUTEX_CHECK_INITIALIZATION if (!_M_initialized) return; # endif # ifdef _DEBUG _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked"); _M_locked = false; # endif _M_mtx_impl.unlock(); } private: fast_mutex(const fast_mutex&); fast_mutex& operator=(const fast_mutex&); }; NVWA_NAMESPACE_END # elif defined(NVWA_PTHREADS) # include NVWA_NAMESPACE_BEGIN /** * Macro alias to `volatile' semantics. Here it is truly volatile since * it is in a multi-threaded (POSIX threads) environment. */ # define __VOLATILE volatile /** * Class for non-reentrant fast mutexes. This is the implementation * for POSIX threads. */ class fast_mutex { pthread_mutex_t _M_mtx_impl; # if _FAST_MUTEX_CHECK_INITIALIZATION bool _M_initialized; # endif # ifdef _DEBUG bool _M_locked; # endif public: fast_mutex() # ifdef _DEBUG : _M_locked(false) # endif { ::pthread_mutex_init(&_M_mtx_impl, NULL); # if _FAST_MUTEX_CHECK_INITIALIZATION _M_initialized = true; # endif } ~fast_mutex() { _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked"); # if _FAST_MUTEX_CHECK_INITIALIZATION _M_initialized = false; # endif ::pthread_mutex_destroy(&_M_mtx_impl); } void lock() { # if _FAST_MUTEX_CHECK_INITIALIZATION if (!_M_initialized) return; # endif ::pthread_mutex_lock(&_M_mtx_impl); # ifdef _DEBUG // The following assertion should _always_ be true for a // real `fast' pthread_mutex. However, this assertion can // help sometimes, when people forget to use `-lpthread' and // glibc provides an empty implementation. Having this // assertion is also more consistent. _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked"); _M_locked = true; # endif } void unlock() { # if _FAST_MUTEX_CHECK_INITIALIZATION if (!_M_initialized) return; # endif # ifdef _DEBUG _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked"); _M_locked = false; # endif ::pthread_mutex_unlock(&_M_mtx_impl); } private: fast_mutex(const fast_mutex&); fast_mutex& operator=(const fast_mutex&); }; NVWA_NAMESPACE_END # elif defined(NVWA_WIN32THREADS) # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif /* WIN32_LEAN_AND_MEAN */ # include NVWA_NAMESPACE_BEGIN /** * Macro alias to `volatile' semantics. Here it is truly volatile since * it is in a multi-threaded (Win32 threads) environment. */ # define __VOLATILE volatile /** * Class for non-reentrant fast mutexes. This is the implementation * for Win32 threads. */ class fast_mutex { CRITICAL_SECTION _M_mtx_impl; # if _FAST_MUTEX_CHECK_INITIALIZATION bool _M_initialized; # endif # ifdef _DEBUG bool _M_locked; # endif public: fast_mutex() # ifdef _DEBUG : _M_locked(false) # endif { ::InitializeCriticalSection(&_M_mtx_impl); # if _FAST_MUTEX_CHECK_INITIALIZATION _M_initialized = true; # endif } ~fast_mutex() { _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked"); # if _FAST_MUTEX_CHECK_INITIALIZATION _M_initialized = false; # endif ::DeleteCriticalSection(&_M_mtx_impl); } void lock() { # if _FAST_MUTEX_CHECK_INITIALIZATION if (!_M_initialized) return; # endif ::EnterCriticalSection(&_M_mtx_impl); # ifdef _DEBUG _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked"); _M_locked = true; # endif } void unlock() { # if _FAST_MUTEX_CHECK_INITIALIZATION if (!_M_initialized) return; # endif # ifdef _DEBUG _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked"); _M_locked = false; # endif ::LeaveCriticalSection(&_M_mtx_impl); } private: fast_mutex(const fast_mutex&); fast_mutex& operator=(const fast_mutex&); }; NVWA_NAMESPACE_END # elif defined(NVWA_NOTHREADS) NVWA_NAMESPACE_BEGIN /** * Macro alias to `volatile' semantics. Here it is not truly volatile * since it is in a single-threaded environment. */ # define __VOLATILE /** * Class for non-reentrant fast mutexes. This is the null * implementation for single-threaded environments. */ class fast_mutex { # ifdef _DEBUG bool _M_locked; # endif public: fast_mutex() # ifdef _DEBUG : _M_locked(false) # endif { } ~fast_mutex() { _FAST_MUTEX_ASSERT(!_M_locked, "~fast_mutex(): still locked"); } void lock() { # ifdef _DEBUG _FAST_MUTEX_ASSERT(!_M_locked, "lock(): already locked"); _M_locked = true; # endif } void unlock() { # ifdef _DEBUG _FAST_MUTEX_ASSERT(_M_locked, "unlock(): not locked"); _M_locked = false; # endif } private: fast_mutex(const fast_mutex&); fast_mutex& operator=(const fast_mutex&); }; NVWA_NAMESPACE_END # endif // Definition of class fast_mutex NVWA_NAMESPACE_BEGIN /** RAII lock class for fast_mutex. */ class fast_mutex_autolock { fast_mutex& _M_mtx; public: explicit fast_mutex_autolock(fast_mutex& mtx) : _M_mtx(mtx) { _M_mtx.lock(); } ~fast_mutex_autolock() { _M_mtx.unlock(); } private: fast_mutex_autolock(const fast_mutex_autolock&); fast_mutex_autolock& operator=(const fast_mutex_autolock&); }; NVWA_NAMESPACE_END #endif // NVWA_FAST_MUTEX_H drc-3.2.2/source/MLeaks/debug_new.h0000644000076400001450000001574012615050550016043 0ustar denisitadm// -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- // vim:tabstop=4:shiftwidth=4:expandtab: /* * Copyright (C) 2004-2015 Wu Yongwei * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute * it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. If you use this * software in a product, an acknowledgement in the product * documentation would be appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must * not be misrepresented as being the original software. * 3. This notice may not be removed or altered from any source * distribution. * * This file is part of Stones of Nvwa: * http://sourceforge.net/projects/nvwa * */ /** * @file debug_new.h * * Header file for checking leaks caused by unmatched new/delete. * * @date 2015-10-25 */ #ifndef NVWA_DEBUG_NEW_H #define NVWA_DEBUG_NEW_H #include // size_t/std::bad_alloc #include // FILE #include "_nvwa.h" // NVWA_NAMESPACE_* #include "c++11.h" // _NOEXCEPT /* Special allocation/deallocation functions in the global scope */ void* operator new(size_t size, const char* file, int line); void* operator new[](size_t size, const char* file, int line); void operator delete(void* ptr, const char* file, int line) _NOEXCEPT; void operator delete[](void* ptr, const char* file, int line) _NOEXCEPT; NVWA_NAMESPACE_BEGIN /** * @def _DEBUG_NEW_REDEFINE_NEW * * Macro to indicate whether redefinition of \c new is wanted. If one * wants to define one's own operator new, or to call * operator new directly, it should be defined to \c 0 to * alter the default behaviour. Unless, of course, one is willing to * take the trouble to write something like: * @code * # ifdef new * # define _NEW_REDEFINED * # undef new * # endif * * // Code that uses new is here * * # ifdef _NEW_REDEFINED * # ifdef DEBUG_NEW * # define new DEBUG_NEW * # endif * # undef _NEW_REDEFINED * # endif * @endcode */ #ifndef _DEBUG_NEW_REDEFINE_NEW #define _DEBUG_NEW_REDEFINE_NEW 1 #endif /** * @def _DEBUG_NEW_TYPE * * Macro to indicate which variant of #DEBUG_NEW is wanted. The * default value \c 1 allows the use of placement new (like * %new(std::nothrow)), but the verbose output (when * nvwa#new_verbose_flag is \c true) looks worse than some older * versions (no file/line information for allocations). Define it * to \c 2 to revert to the old behaviour that records file and line * information directly on the call to operator new. */ #ifndef _DEBUG_NEW_TYPE #define _DEBUG_NEW_TYPE 1 #endif /** * Callback type for stack trace printing. * * @param fp pointer to the output stream * @param stacktrace pointer to the stack trace array (null-terminated) */ typedef void (*stacktrace_print_callback_t)(FILE* fp, void** stacktrace); /** * Callback type for the leak whitelist function. \a file, \a address, * and \a backtrace might be null depending on library configuration, * platform, and amount of runtime information available. \a line can * be 0 when line number info is not available at runtime. * * @param file null-terminated string of the file name * @param line line number * @param addr address of code where leakage happens * @param stacktrace pointer to the stack trace array (null-terminated) * @return \c true if the leak should be whitelisted; * \c false otherwise */ typedef bool (*leak_whitelist_callback_t)(char const* file, int line, void* addr, void** stacktrace); /* Prototypes */ int check_leaks(); int check_mem_corruption(); /* Control variables */ extern bool new_autocheck_flag; // default to true: call check_leaks() on exit extern bool new_verbose_flag; // default to false: no verbose information extern FILE* new_output_fp; // default to stderr: output to console extern const char* new_progname;// default to null; should be assigned argv[0] extern stacktrace_print_callback_t stacktrace_print_callback;// default to null extern leak_whitelist_callback_t leak_whitelist_callback; // default to null /** * @def DEBUG_NEW * * Macro to catch file/line information on allocation. If * #_DEBUG_NEW_REDEFINE_NEW is \c 0, one can use this macro directly; * otherwise \c new will be defined to it, and one must use \c new * instead. */ # if _DEBUG_NEW_TYPE == 1 # define DEBUG_NEW NVWA::debug_new_recorder(__FILE__, __LINE__) ->* new # else # define DEBUG_NEW new(__FILE__, __LINE__) # endif # if _DEBUG_NEW_REDEFINE_NEW # define new DEBUG_NEW # endif # ifdef _DEBUG_NEW_EMULATE_MALLOC # include # ifdef new # define malloc(s) ((void*)(new char[s])) # else # define malloc(s) ((void*)(DEBUG_NEW char[s])) # endif # define free(p) delete[] (char*)(p) # endif /** * Recorder class to remember the call context. * * The idea comes from Greg Herlihy's post in comp.lang.c++.moderated. */ class debug_new_recorder { const char* _M_file; const int _M_line; void _M_process(void* ptr); public: /** * Constructor to remember the call context. The information will * be used in debug_new_recorder::operator->*. */ debug_new_recorder(const char* file, int line) : _M_file(file), _M_line(line) {} /** * Operator to write the context information to memory. * operator->* is chosen because it has the right * precedence, it is rarely used, and it looks good: so people can * tell the special usage more quickly. */ template _Tp* operator->*(_Tp* ptr) { _M_process(ptr); return ptr; } private: debug_new_recorder(const debug_new_recorder&); debug_new_recorder& operator=(const debug_new_recorder&); }; /** * Counter class for on-exit leakage check. * * This technique is learnt from The C++ Programming Language by * Bjarne Stroustup. */ class debug_new_counter { static int _S_count; public: debug_new_counter(); ~debug_new_counter(); }; /** Counting object for each file including debug_new.h. */ static debug_new_counter __debug_new_count; NVWA_NAMESPACE_END #endif // NVWA_DEBUG_NEW_H drc-3.2.2/source/MLeaks/README0000644000076400001450000003026013066737767014634 0ustar denisitadm === Stones of Nvwa === The Name Nvwa ("v" is pronounced like the French "u"), is one of the most ancient Chinese goddesses. She was said to have created human beings, and, when the evil god Gong-gong crashed himself upon one of the pillars that support the sky and made a hole in it, she mended the sky with five-coloured stones. I thought of the name Nvwa by analogy with Loki. Since it is so small a project and it contains utilities instead of a complete framework, I think "stones" a good metaphor. Code Organization Nvwa versions prior to 1.0 did not use a namespace. It looked to me overkill to use a namespace in this small project. However, having had more project experience and seen more good examples, I have changed my mind. All nvwa functions and global variables are now inside the namespace "nvwa". This said, I do not want to break backward compatibility abruptly. First, people are still able to disable the namespace by defining the macro NVWA_USE_NAMESPACE to 0 (not really recommended, though). Second, I still use the quotation mark (") to include header files internally so that old users do not have to change the include directory (again, not recommended and intended to help the transition only). Third, I have not changed most of the macro names -- that would break existing code and could do more harm than good now. In addition, I am not a fan of macro prefixes anyway. Overall, I am quite happy with the changes: some code is simplified, and in many cases I do not have to use the uglified names to avoid potential name conflicts. The changes also do not mean anything to new users. You just need to follow the modern C++ way. You should add the root directory of this project to your include directory (there should be a "nvwa" directory inside it with the source files). To include the header file, use "#include ". Contents A brief introduction follows. Check the Doxygen documentation for more (technical) details. * boolarray.cpp * boolarray.h A replacement of std::vector. I wrote it before I knew of vector, or I might not have written it at all. However, it is faster than many vector implementations (your mileage may vary), and it has members like at, set, reset, flip, and count. I personally find "count" very useful. * c++11.h Detection macros for certain features of C++11 that might be of interest to code/library writers. I have used existing online resources, and I have tested them on popular platforms and compilers that I have access to (Windows, OS X, and Linux; MSVC, Clang, and GCC), but of course not all versions or all combinations. Patches are welcome for corrections and amendments. * class_level_lock.h The Loki ClassLevelLockable adapted to use the fast_mutex layer. One minor divergence from Loki is that the template has an additional template parameter _RealLock to boost the performance in non-locking scenarios. Unless HAVE_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION is explicitly defined to 0, this is enabled automatically. Cf. object_level_lock.h. * cont_ptr_utils.h Utility functors for containers of pointers adapted from Scott Meyers' Effective STL. * debug_new.cpp * debug_new.h A cross-platform, thread-safe memory leak detector. It is a light-weight one designed only to catch unmatched pairs of new/delete. I know there are already many existing memory leak detectors, but as far as I know, free solutions are generally slow, memory-consuming, and quite complicated to use. This solution is very easy to use, and has very low space/time overheads. Just link in debug_new.cpp for leakage report, and include debug_new.h for additional file/line information. It will automatically switch on multi-threading when the appropriate option of a recognized compiler is specified. Check fast_mutex.h for more threading details. Special support for gcc/binutils has been added to debug_new lately. Even if the header file debug_new.h is not included, or _DEBUG_NEW_REDEFINE_NEW is defined to 0 when it is included, file/line information can be displayed if debugging symbols are present in the executable, since debug_new stores the caller addresses of memory allocation/deallocation routines and they will be converted with addr2line (or atos on a Mac) on the fly. This makes memory tracing much easier. NOTE for Mac OS X users: If you use OS X 10.7 or later, you may need to add "-Wl,-no_pie" at the end of the command line. By default OS X will now create position-independent executables (PIE), and the OS will load a PIE at a random address each time it is executed, making it difficult to convert the address to symbols. (I Googled a while for a way to get the base address of a process, but could not find working code. If you know how to do it right, drop me a message.) With an idea from Greg Herlihy's post in comp.lang.c++.moderated, the implementation was much improved in 2007. The most significant result is that placement new can be used with debug_new now! Full support for new(std::nothrow) is provided, with its null-returning error semantics (by default). Memory corruption will be checked on freeing the pointers and checking the leaks, and a new function check_mem_corruption is added for your on-demand use in debugging. You may also want to define _DEBUG_NEW_TAILCHECK to something like 4 for past-end memory corruption check, which is off by default to ensure performance is not affected. An article on its design and implementation is available at http://nvwa.sourceforge.net/article/debug_new.htm * fast_mutex.h The threading transparent layer simulating a non-recursive mutex. It supports C++11 mutex, POSIX mutex, and Win32 critical section, as well as a no-threads mode. Unlike Loki and some other libraries, threading mode is not to be specified in code, but detected from the environment. It will automatically switch on multi-threading mode (inter-thread exclusion) when the "-MT"/"-MD" option of MSVC, the "-mthreads" option of MinGW GCC, or the "-pthread" option of GCC under POSIX environments, is used. One advantage of the current implementation is that the construction and destruction of a static object using a static fast_mutex not yet constructed or already destroyed are allowed to work (with lock/unlock operations ignored), and there are re-entry checks for lock/unlock operations when the preprocessing symbol _DEBUG is defined. * fc_queue.h A queue that has a fixed capacity (maximum number of allowed items). All memory is pre-allocated when the queue is initialized, so memory consumption is well controlled. When the queue is full, inserting a new item will discard the oldest item in the queue. Care is taken to ensure this class template provides the strong exception safety guarantee. This class template is a good exercise for me to make a STL-type container. Depending on your needs, you may find circular_buffer in Boost more useful, which provides similar functionalities and a richer API. However, the design philosophies behind the two implementations are quite different. fc_queue is modelled closely on std::queue, and I optimize mainly for a lockless producer-consumer pattern -- when there is one producer and one consumer, and the producer does not try to queue an element when the queue is already full, no lock is needed for the queue operations. * file_line_reader.cpp * file_line_reader.h This is one of the line reading classes I implemented modelling the Python approach. They make reading lines from a file a simple loop. This specific class allows reading from a traditional FILE*. Cf. istream_line_reader.h and mmap_line_reader.h. See the following blog for the motivation and example code: https://yongweiwu.wordpress.com/2016/11/12/performance-of-my-line-readers/ * fixed_mem_pool.h A memory pool implementation that requires initialization (allocates a fixed-size chunk) prior to its use. It is simple and makes no memory fragmentation, but the memory pool size cannot be changed after initialization. Macros are provided to easily make a class use pooled new/delete. * functional.h This is my test bed for functional programming. If you are into functional programming, check it out. It includes functional programming patterns like: - map - reduce - compose - fixed-point combinator - curry - optional My blogs on functional programming may be helpful: https://yongweiwu.wordpress.com/2014/12/07/study-notes-functional-programming-with-cplusplus/ https://yongweiwu.wordpress.com/2014/12/14/y-combinator-and-cplusplus/ https://yongweiwu.wordpress.com/2014/12/29/type-deduction-and-my-reference-mistakes/ https://yongweiwu.wordpress.com/2015/01/03/generic-lambdas-and-the-compose-function/ * istream_line_reader.h This is one of the line reading classes I implemented modelling the Python approach. They make reading lines from a file a simple loop. This specific class allows reading from an input stream. Cf. file_line_reader.h and mmap_line_reader.h. See the following blogs for the motivation and example code: https://yongweiwu.wordpress.com/2016/08/16/python-yield-and-cplusplus-coroutines/ https://yongweiwu.wordpress.com/2016/11/12/performance-of-my-line-readers/ * mem_pool_base.cpp * mem_pool_base.h A class solely to be inherited by memory pool implementations. It is used by static_mem_pool and fixed_mem_pool. * mmap_line_reader.cpp * mmap_line_reader.h This is one of the line reading classes I implemented modelling the Python approach. They make reading lines from a file a simple loop. This specific class allows reading from an on-disk file via memory- mapped file I/O. Cf. istream_line_reader.h and file_line_reader.h. See the following blog for the motivation and example code: https://yongweiwu.wordpress.com/2016/11/12/performance-of-my-line-readers/ * object_level_lock.h The Loki ObjectLevelLockable adapted to use the fast_mutex layer. The member function get_locked_object does not exist in Loki, but is also taken from Mr Alexandrescu's article. Cf. class_level_lock.h. * pctimer.h A function to get a high-resolution timer for Win32/Cygwin/Unix. It is quite useful for measurement and optimization. * set_assign.h Utility routines to make up for the fact that STL only has set_union (+) and set_difference (-) algorithms but no corresponding += and -= operations available. * static_mem_pool.cpp * static_mem_pool.h A memory pool implementation to pool memory blocks according to compile-time block sizes. Macros are provided to easily make a class use pooled new/delete. An article on its design and implementation is available at http://nvwa.sourceforge.net/article/static_mem_pool.htm * tree.h A generic tree class template along with traversal utilities. Besides the usual template argument of value type, it has an additional argument of storage policy, which can be either unique or shared. Traversal utility classed are provided so that traversing a tree can be simply done in a range-based for loop. The test code, test/test_tree.cpp, shows its basic usage. * type_traits.h This file was separated from fc_queue.h. Type traits were not standardized until C++11, and, in addition, there were late changes in the trait names that did not go into even the 2012 releases of MSVC and GCC. So I made a nvwa::is_trivially_destructible that can work across main compilers. In the post-C++11 world, this is no longer useful. Use of this file is deprecated. $Id: README,v 1.1 2017/03/29 14:08:55 adah Exp $ vim:autoindent:expandtab:formatoptions=tcqlm:textwidth=72: drc-3.2.2/source/drccfg.h0000644000076400001450000001600413162156445014162 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2017 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@neomerica.it ****************************************************************************/ /* Opzioni di configurazione DRC */ #ifndef DRCCfg_h #define DRCCfg_h /* Inclusioni */ #include "drc.h" #include "cmdline.h" /* Posizione opzione directory base di configurazione nella lista parametri */ #define BCBaseDirParmPos 0 /* Struttura definizione configurazione */ /* Prefissi variabili BC = Base Configuration HD = Homomorphic Deconvolution MP = Minimum phase frequency dependent windowing DL = Dip limiting stage EP = Excess phase frequency dependent windowing PC = Prefiltering completion stage IS = Inversion stage PT = Psychoacoustic target stage PL = Peak limiting stage RT = Ringing truncation stage PS = Postfiltering stage MC = Mic compensation stage MS = Minimum phase filter extraction stage TC = Test convolution stage */ typedef struct { /* Base configuration */ char * BCBaseDir; char * BCInFile; char * BCInFileType; int BCSampleRate; char * BCImpulseCenterMode; int BCImpulseCenter; int BCInitWindow; int BCPreWindowLen; int BCPreWindowGap; DRCFloat BCNormFactor; char * BCNormType; /* Mic compensation stage */ char * MCFilterType; char * MCInterpolationType; int MCMultExponent; int MCFilterLen; int MCNumPoints; char * MCPointsFile; char * MCMagType; int MCOutWindow; char * MCFilterFile; char * MCFilterFileType; DRCFloat MCNormFactor; char * MCNormType; char * MCOutFile; char * MCOutFileType; /* Base configuration dip limiting stage */ char * BCDLType; DRCFloat BCDLMinGain; DRCFloat BCDLStart; DRCFloat BCDLStartFreq; DRCFloat BCDLEndFreq; int BCDLMultExponent; /* Homomorphic Deconvolution */ int HDMultExponent; DRCFloat HDMPNormFactor; char * HDMPNormType; char * HDMPOutFile; char * HDMPOutFileType; DRCFloat HDEPNormFactor; char * HDEPNormType; char * HDEPOutFile; char * HDEPOutFileType; /* Minimum phase prefiltering stage */ char * MPPrefilterType; char * MPPrefilterFctn; int MPWindowGap; int MPLowerWindow; int MPUpperWindow; DRCFloat MPStartFreq; DRCFloat MPEndFreq; DRCFloat MPWindowExponent; int MPFilterLen; DRCFloat MPFSharpness; int MPBandSplit; char * MPHDRecover; char * MPEPPreserve; int MPHDMultExponent; int MPPFFinalWindow; DRCFloat MPPFNormFactor; char * MPPFNormType; char * MPPFOutFile; char * MPPFOutFileType; /* Dip limiting stage */ char * DLType; DRCFloat DLMinGain; DRCFloat DLStart; DRCFloat DLStartFreq; DRCFloat DLEndFreq; int DLMultExponent; /* Excess fase phase prefiltering stage */ char * EPPrefilterType; char * EPPrefilterFctn; int EPWindowGap; int EPLowerWindow; int EPUpperWindow; DRCFloat EPStartFreq; DRCFloat EPEndFreq; DRCFloat EPWindowExponent; int EPFilterLen; DRCFloat EPFSharpness; int EPBandSplit; DRCFloat EPPFFlatGain; DRCFloat EPPFOGainFactor; char * EPPFFlatType; int EPPFFGMultExponent; int EPPFFinalWindow; DRCFloat EPPFNormFactor; char * EPPFNormType; char * EPPFOutFile; char * EPPFOutFileType; /* Prefiltering completion stage */ int PCOutWindow; DRCFloat PCNormFactor; char * PCNormType; char * PCOutFile; char * PCOutFileType; /* Inversion stage */ char * ISType; char * ISPETType; char * ISPrefilterFctn; int ISPELowerWindow; int ISPEUpperWindow; int ISPEStartFreq; int ISPEEndFreq; int ISPEFilterLen; DRCFloat ISPEFSharpness; int ISPEBandSplit; DRCFloat ISPEWindowExponent; DRCFloat ISPEOGainFactor; int ISSMPMultExponent; int ISOutWindow; DRCFloat ISNormFactor; char * ISNormType; char * ISOutFile; char * ISOutFileType; /* Psychoacoustic target stage */ char * PTType; int PTReferenceWindow; char * PTDLType; DRCFloat PTDLMinGain; DRCFloat PTDLStart; DRCFloat PTDLStartFreq; DRCFloat PTDLEndFreq; int PTDLMultExponent; DRCFloat PTBandWidth; DRCFloat PTPeakDetectionStrength; int PTMultExponent; int PTFilterLen; char * PTFilterFile; char * PTFilterFileType; DRCFloat PTNormFactor; char * PTNormType; char * PTOutFile; char * PTOutFileType; int PTOutWindow; /* Peak limiting stage */ char * PLType; DRCFloat PLMaxGain; DRCFloat PLStart; DRCFloat PLStartFreq; DRCFloat PLEndFreq; int PLMultExponent; int PLOutWindow; DRCFloat PLNormFactor; char * PLNormType; char * PLOutFile; char * PLOutFileType; /* Ringing truncation stage */ char * RTType; char * RTPrefilterFctn; int RTWindowGap; int RTLowerWindow; int RTUpperWindow; DRCFloat RTStartFreq; DRCFloat RTEndFreq; DRCFloat RTWindowExponent; int RTFilterLen; DRCFloat RTFSharpness; int RTBandSplit; int RTOutWindow; DRCFloat RTNormFactor; char * RTNormType; char * RTOutFile; char * RTOutFileType; /* Target response stage */ char * PSFilterType; char * PSInterpolationType; int PSMultExponent; int PSFilterLen; int PSNumPoints; char * PSPointsFile; char * PSMagType; int PSOutWindow; DRCFloat PSNormFactor; char * PSNormType; char * PSOutFile; char * PSOutFileType; /* Minimum phase filter extraction stage */ int MSMultExponent; int MSOutWindow; int MSFilterDelay; DRCFloat MSNormFactor; char * MSNormType; char * MSOutFile; char * MSOutFileType; /* Test convolution stage */ DRCFloat TCNormFactor; char * TCNormType; char * TCOutFile; char * TCOutFileType; char * TCOWFile; char * TCOWFileType; DRCFloat TCOWNormFactor; char * TCOWNormType; int TCOWSkip; int TCOWPrewindow; int TCOWLength; } CfgParmsType; /* Opzioni di configurazione */ extern CfgParmsType Cfg; /* Definizione struttura file di configurazione */ extern CfgParameter CfgParmsDef[]; /* Controllo validit parametri di configurazione */ int CheckDRCCfg(const CfgParmsType * DRCCfg); /* Impostazione directory base di lavoro */ int SetupDRCCfgBaseDir(CfgParmsType * DRCCfg, const CfgParameter * CfgParmsDef, const CmdLineType * OptData); #endif drc-3.2.2/source/baselib.cpp0000644000076400001450000004402713162156311014664 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Funzioni di libreria base */ /* Inclusioni */ #include "baselib.h" #include "fft.h" #include #include #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Output stringhe con sync output e parametro */ int sputsp(const char * s, const char * p) { int Res; if (p == NULL) Res = puts(s); else Res = printf("%s%s\n",s,p); fflush(stdout); return(Res); } /* Output stringhe con sync output */ int sputs(const char * s) { return(sputsp(s, NULL)); } /* Determina la lunghezza di un file */ size_t FSize(FILE * F) { long CPos; long FS; CPos = ftell(F); fseek(F,0,SEEK_END); FS = ftell(F); fseek(F,CPos,SEEK_SET); return (size_t) FS; } /* Legge parte di un file di ingresso e lo pone nell'array indicato di dimensione InitWindow. Ritorna true se l'operazione ha successo. */ Boolean ReadSignal(const char * FName,DRCFloat * Dst,const int InitWindow, const int ImpulseCenter,const IFileType FType, int * PreSpikeStart, int * PostSpikeEnd) { int I; int IStart; int IEnd; int WHalf; DRCFileDouble RWD; DRCFileFloat RWF; DRCFileInt RWI; int RWDim; /* File gestione IO */ FILE * IOF; long FS; /* Azzera l'array destinazione */ for (I = 0;I < InitWindow;I++) Dst[I] = 0; /* Salva la dimensione del blocco lettura */ RWDim = sizeof(DRCFileFloat); switch (FType) { case PcmFloat64Bit: RWDim = sizeof(DRCFileDouble); break; case PcmFloat32Bit: RWDim = sizeof(DRCFileFloat); break; case PcmInt16Bit: RWDim = sizeof(DRCFileInt); break; } /* Apre il file di input */ if ((IOF = fopen(FName,"rb")) == NULL) { perror("\nUnable to open input file"); return False; } /* Recupera la dimensione del file */ FS = FSize(IOF) / RWDim; /* Controllo validit parametri */ if (FS == 0) { puts("\nInput file is zero length."); return False; } if (ImpulseCenter > FS) { puts("\nImpulseCenter is out of input file range."); return False; } /* Calcolo la posizione centrale finestra */ if (InitWindow % 2 == 0) WHalf = (InitWindow - 1) / 2; else WHalf = InitWindow / 2; /* Calcola gli estremi lettura finestra */ if (ImpulseCenter > WHalf) { if (fseek(IOF,(ImpulseCenter - WHalf) * RWDim,SEEK_SET) != 0) { perror("\nError reading input file"); return False; } IStart = 0; if (InitWindow > FS - (ImpulseCenter - WHalf)) IEnd = FS - (ImpulseCenter - WHalf); else IEnd = InitWindow; } else { IStart = WHalf - ImpulseCenter; if (InitWindow > IStart + FS) IEnd = IStart + FS; else IEnd = InitWindow; } /* Imposta inizio pre spike */ if (PreSpikeStart != NULL) *PreSpikeStart = IStart; /* Imposta fine post spike */ if (PostSpikeEnd != NULL) *PostSpikeEnd = IEnd; /* Legge la risposta all'impulso */ switch (FType) { case PcmFloat64Bit: for (I = IStart; I < IEnd; I++) { if (fread((void *) &RWD,sizeof(DRCFileDouble),1,IOF) != 1) { perror("\nError reading input file"); return False; } Dst[I] = (DLReal) RWD; } break; case PcmFloat32Bit: for (I = IStart; I < IEnd; I++) { if (fread((void *) &RWF,sizeof(DRCFileFloat),1,IOF) != 1) { perror("\nError reading input file"); return False; } Dst[I] = (DLReal) RWF; } break; case PcmInt16Bit: for (I = IStart; I < IEnd; I++) { if (fread((void *) &RWI,sizeof(DRCFileInt),1,IOF) != 1) { perror("\nError reading input file"); return False; } Dst[I] = (DLReal) RWI; } break; } /* Chiude il file */ fclose(IOF); /* Operazione completata */ return True; } /* Scrive il segnale indicato su disco */ Boolean WriteSignal(const char * FName,const DRCFloat * Src,const int SSize, const IFileType FType) { /* File gestione IO */ FILE * IOF; int I; DRCFileDouble RWD; DRCFileFloat RWF; DRCFileInt RWI; /* Apre il file di output */ if ((IOF = fopen(FName,"wb")) == NULL) { perror("\nUnable to open output file"); return False; } /* Salva la risposta risultante */ switch (FType) { case PcmFloat64Bit: for (I = 0; I < SSize; I++) { RWD = (DRCFileDouble) Src[I]; if (fwrite((void *) &RWD,sizeof(DRCFileDouble),1,IOF) != 1) { perror("\nError writing output file"); return False; } } break; case PcmFloat32Bit: for (I = 0; I < SSize; I++) { RWF = (DRCFileFloat) Src[I]; if (fwrite((void *) &RWF,sizeof(DRCFileFloat),1,IOF) != 1) { perror("\nError writing output file"); return False; } } break; case PcmInt16Bit: for (I = 0; I < SSize; I++) { RWI = (DRCFileInt) floor(0.5 + Src[I]); if (fwrite((void *) &RWI,sizeof(DRCFileInt),1,IOF) != 1) { perror("\nError writing output file"); return False; } } break; } /* Chiude il file */ fclose(IOF); /* Operazione completata */ return True; } /* Sovrascrive il segnale indicato su disco */ Boolean OverwriteSignal(const char * FName,const DRCFloat * Src,const int SSize, const int Skip, const IFileType FType) { /* File gestione IO */ FILE * IOF; int I; DRCFileDouble RWD; DRCFileFloat RWF; DRCFileInt RWI; /* Apre il file di output */ IOF = fopen(FName,"r+b"); /* Salva la risposta risultante */ switch (FType) { case PcmFloat64Bit: fseek(IOF,Skip * sizeof(DRCFileDouble), SEEK_SET); for (I = 0; I < SSize; I++) { RWD = (DRCFileDouble) Src[I]; if (fwrite((void *) &RWD,sizeof(DRCFileDouble),1,IOF) != 1) { perror("\nError writing output file."); return False; } } break; case PcmFloat32Bit: fseek(IOF,Skip * sizeof(DRCFileFloat), SEEK_SET); for (I = 0; I < SSize; I++) { RWF = (DRCFileFloat) Src[I]; if (fwrite((void *) &RWF,sizeof(DRCFileFloat),1,IOF) != 1) { perror("\nError writing output file."); return False; } } break; case PcmInt16Bit: fseek(IOF,Skip * sizeof(DRCFileInt), SEEK_SET); for (I = 0; I < SSize; I++) { RWI = (DRCFileInt) floor(0.5 + Src[I]); if (fwrite((void *) &RWI,sizeof(DRCFileInt),1,IOF) != 1) { perror("\nError writing output file."); return False; } } break; } /* Chiude il file */ fclose(IOF); /* Operazione completata */ return True; } /* Calcola l'autocorrelazione del segnale S */ Boolean AutoCorrelation(DLReal * S, int N) { DLComplex * C; int I; if ((C = new DLComplex[N]) == NULL) return False; for (I = 0; I < N; I++) C[I] = S[I]; Fft(C,N); for (I = 0; I < N; I++) /* C[I] = C[I] * std::conj(C[I]); */ C[I] = std::real(C[I]) * std::real(C[I]) + std::imag(C[I]) * std::imag(C[I]); IFft(C,N); for (I = 0; I < N; I++) S[I] = std::real(C[I]) / N; delete[] C; return True; } /* Calcola la cross correlazione tra S1 e S2 */ /* XC deve avere lunghezza 2N - 1 */ Boolean CrossCorrelation(DLReal * S1, DLReal * S2, int N, DLReal * XC) { DLComplex * C1; DLComplex * C2; int I; if ((C1 = new DLComplex[2 * N]) == NULL) return False; if ((C2 = new DLComplex[2 * N]) == NULL) { delete[] C1; return False; } for (I = 0; I < N; I++) { C1[I] = S1[I]; C2[I] = S2[I]; } for (I = N; I < 2 * N; I++) { C1[I] = 0; C2[I] = 0; } Fft(C1,2 * N); Fft(C2,2 * N); for (I = 0; I < 2 * N; I++) C1[I] *= std::conj(C2[I]); delete[] C2; IFft(C1,2 * N); for (I = 0; I < 2 * N - 1; I++) XC[I] = std::real(C1[I]) / N; delete[] C1; return True; } /* Calcola il ritardo di gruppo del segnale S */ Boolean GroupDelay(const DLReal * S, const int N, DLReal * GD) { DLComplex * HA; DLComplex * DHA; int I; if ((HA = new DLComplex[N]) == NULL) return False; if ((DHA = new DLComplex[N]) == NULL) { delete[] HA; return False; } for(I = 0;I < N;I++) { HA[I] = S[I]; DHA[I] = S[I] * I; } Fft(HA,N); Fft(DHA,N); for(I = 0;I < N;I++) GD[I] = std::real(DHA[I] / HA[I]); delete[] HA; delete[] DHA; return True; } /* I/O Delay computation, reliable only for simple impulse responses */ DLReal LinearDelay(DLReal * Hn,unsigned int N,unsigned int Np, DLReal MZE) { unsigned int I; DLComplex * H; DLComplex * H1; DLComplex Sum,i(0,1); if (Np == 0) for(Np = 2;Np < N;Np <<= 1); Np = 2*Np; if ((H = new DLComplex[Np]) == NULL) return(-1); if ((H1 = new DLComplex[Np]) == NULL) { delete[](H); return(-1); } for(I = 0;I < N;I++) H[I] = Hn[I]; for(I = N;I < Np;I++) H[I] = 0; if (Fft(H,Np) == False) { delete[](H); delete[](H1); return(-1); } for(I = 0;I < N;I++) H1[I] = I*Hn[I]; for(I = N;I < Np;I++) H1[I] = 0; if (Fft(H1,Np) == False) { delete[](H); delete[](H1); return(-1); } for(I = 0;I < Np;I++) if (std::abs(H[I]) <= MZE) { H[I] = 1; H1[I] = 0; } Sum = 0; for(I = 0;I < Np;I++) Sum += (-i*H1[I])/H[I]; delete[](H); delete[](H1); return(std::real(-Sum/(i*(DLReal) Np))); } /* Conta il numero di righe in un file */ int FLineCount(const char * FName) { /* File gestione IO */ FILE * IOF; /* Variabili ausiliarie */ int LC; char InStr[256]; /* Apre il file di input */ if ((IOF = fopen(FName,"rt")) == NULL) { perror("\nUnable to open input file."); return False; } /* Conta le righe */ LC = 0; while (fgets(InStr,256,IOF) != NULL) LC++; /* Chiude il file di input */ fclose(IOF); /* Ritorna il numero di righe */ return LC; } /* Legge i punti di generazione filtro FIR dal file indicato */ Boolean ReadPoints(char * CorrFile,const TFMagType MagType, DLReal * FilterFreqs,DLReal * FilterM,DLReal * FilterP,const int NPoints, int SampleRate) { /* File gestione IO */ FILE * IOF; /* Variabili ausiliarie */ int I; float Freq; float Mag; float Phase; char InStr[256]; /* Apre il file di correzione */ if ((IOF = fopen(CorrFile,"rt")) == NULL) { perror("\nUnable to open correction file."); return False; } /* Legge i valori */ for (I = 0; I < NPoints; I++) { if (fgets(InStr,256,IOF) == NULL) { perror("\nError reading correction file"); return False; } Phase = 0; if (sscanf(InStr,"%f %f %f",&Freq,&Mag,&Phase) < 2) { printf("Not enough parameters on line %d.",I); sputs("Error reading correction file."); return False; } /* Verifica il tipo di ampiezza */ if (MagType == MAGdB) /* Ricava l'ampiezza assoluta dai dB */ Mag = (DLReal) pow(10.0,Mag / 20.0); /* Imposta i punti per il filtro */ FilterFreqs[I] = (DLReal) (2 * Freq) / SampleRate; FilterM[I] = (DLReal) Mag; FilterP[I] = (DLReal) ((Phase * M_PI) / 180); } FilterFreqs[NPoints - 1] = (DLReal) 1.0; /* Chiude il file di input */ fclose(IOF); /* Operazione completata */ return True; } /* Integra due funzioni di trsferimento definite per punti, usando una interpolazione lineare, ritorna il numero di punti generati, che non sono mai pi di NPoints1 + NPoints2 */ int LITFMerge(DLReal * FilterFreqs1,DLComplex * FilterPoints1,const int NPoints1, DLReal * FilterFreqs2,DLComplex * FilterPoints2,const int NPoints2, DLReal * FilterFreqsOut,DLComplex * FilterPointsOut) { /* Indice sull'array di output */ int OI; /* Indice sugli array di ingresso */ int I1; int I2; /* Calcolo interpolazione */ DLReal DMag; DLReal DArg; DLReal DFreq; /* Inizializza gli indici ciclo interpolazione */ OI = 0; I1 = 0; I2 = 0; /* Ciclo interpolazione */ while (I1 < NPoints1 || I2 < NPoints2) { if (FilterFreqs1[I1] == FilterFreqs2[I2]) { /* Calcola il punto di uscita */ FilterFreqsOut[OI] = FilterFreqs1[I1]; FilterPointsOut[OI] = FilterPoints1[I1] * FilterPoints2[I2]; /* Avanza gli indici elaborati */ I1++; I2++; } else if (FilterFreqs1[I1] > FilterFreqs2[I2]) { /* Calcola la frequeunza del punto di uscita */ FilterFreqsOut[OI] = FilterFreqs2[I2]; /* Calcola le variazioni per l'interpolazione */ DMag = std::abs(FilterPoints1[I1]) - std::abs(FilterPoints1[I1 - 1]); DArg = std::arg(FilterPoints1[I1]) - std::arg(FilterPoints1[I1 - 1]); DFreq = FilterFreqs1[I1] - FilterFreqs1[I1 - 1]; /* Calcola il punto di uscita */ FilterPointsOut[OI] = FilterPoints2[I2] * std::polar(std::abs(FilterPoints1[I1 - 1]) + (FilterFreqsOut[OI] - FilterFreqs1[I1 - 1]) * DMag / DFreq, std::arg(FilterPoints1[I1 - 1]) + (FilterFreqsOut[OI] - FilterFreqs1[I1 - 1]) * DArg / DFreq); /* Avanza l'indice elaborato */ I2++; } else { /* Calcola la frequeunza del punto di uscita */ FilterFreqsOut[OI] = FilterFreqs1[I1]; /* Calcola le variazioni per l'interpolazione */ DMag = std::abs(FilterPoints2[I2]) - std::abs(FilterPoints2[I2 - 1]); DArg = std::arg(FilterPoints2[I2]) - std::arg(FilterPoints2[I2 - 1]); DFreq = FilterFreqs2[I2] - FilterFreqs2[I2 - 1]; /* Calcola il punto di uscita */ FilterPointsOut[OI] = FilterPoints1[I1] * std::polar(std::abs(FilterPoints2[I2 - 1]) + (FilterFreqsOut[OI] - FilterFreqs2[I2 - 1]) * DMag / DFreq, std::arg(FilterPoints2[I2 - 1]) + (FilterFreqsOut[OI] - FilterFreqs2[I2 - 1]) * DArg / DFreq); /* Avanza l'indice elaborato */ I1++; } /* Avanza l'indice di uscita */ OI++; } /* Ritorna il numero punti generati */ return OI; } /* Trova il valore massimo all'interno di un file. Versione float 64 bit. */ static int FindMaxPcmFloat64Bit(const char * FName) { DRCFileDouble RWD; int MaxPos; int Pos; DRCFileDouble PcmMax; /* File gestione IO */ FILE * IOF; /* Apre il file di input */ if ((IOF = fopen(FName,"rb")) == NULL) { perror("\nUnable to open input file."); return -1; } /* Ciclo ricerca massimo */ Pos = 0; MaxPos = 0; PcmMax = 0; while(feof(IOF) == 0) { if (fread((void *) &RWD,sizeof(DRCFileDouble),1,IOF) != 1) { if (feof(IOF) == 0) { perror("\nError reading input file."); return -1; } } if (((DRCFileFloat) fabs(RWD)) > PcmMax) { PcmMax = (DRCFileFloat) fabs(RWD); MaxPos = Pos; } Pos++; } /* Chiude il file di input */ fclose(IOF); /* Operazione completata */ return MaxPos; } /* Trova il valore massimo all'interno di un file. Versione float 32 bit. */ static int FindMaxPcmFloat32Bit(const char * FName) { DRCFileFloat RWF; int MaxPos; int Pos; DRCFileFloat PcmMax; /* File gestione IO */ FILE * IOF; /* Apre il file di input */ if ((IOF = fopen(FName,"rb")) == NULL) { perror("\nUnable to open input file."); return -1; } /* Ciclo ricerca massimo */ Pos = 0; MaxPos = 0; PcmMax = 0; while(feof(IOF) == 0) { if (fread((void *) &RWF,sizeof(DRCFileFloat),1,IOF) != 1) { if (feof(IOF) == 0) { perror("\nError reading input file."); return -1; } } if (((DRCFileFloat) fabs(RWF)) > PcmMax) { PcmMax = (DRCFileFloat) fabs(RWF); MaxPos = Pos; } Pos++; } /* Chiude il file di input */ fclose(IOF); /* Operazione completata */ return MaxPos; } /* Trova il valore massimo all'interno di un file. Versione int 16 Bit. */ static int FindMaxPcmInt16Bit(const char * FName) { DRCFileInt RWI; int MaxPos; int Pos; DRCFileInt PcmMax; /* File gestione IO */ FILE * IOF; /* Apre il file di input */ if ((IOF = fopen(FName,"rb")) == NULL) { perror("\nUnable to open input file."); return -1; } /* Ciclo ricerca massimo */ Pos = 0; MaxPos = 0; PcmMax = 0; while(feof(IOF) == 0) { if (fread((void *) &RWI,sizeof(DRCFileInt),1,IOF) != 1) { if (feof(IOF) == 0) { perror("\nError reading input file."); return -1; } } if (((DRCFileInt) abs(RWI)) > PcmMax) { PcmMax = (DRCFileInt) abs(RWI); MaxPos = Pos; } Pos++; } /* Chiude il file di input */ fclose(IOF); /* Operazione completata */ return MaxPos; } /* Trova il valore massimo all'interno di un file. */ int FindMaxPcm(const char * FName,const IFileType FType) { /* Controlla il tipo file */ switch (FType) { case PcmFloat64Bit: return FindMaxPcmFloat64Bit(FName); case PcmFloat32Bit: return FindMaxPcmFloat32Bit(FName); case PcmInt16Bit: return FindMaxPcmInt16Bit(FName); } /* Tipo file errato */ return -1; } drc-3.2.2/source/target/0000755000076400001450000000000013165107361014042 5ustar denisitadmdrc-3.2.2/source/target/48.0 kHz/0000755000076400001450000000000013165107361015150 5ustar denisitadmdrc-3.2.2/source/target/48.0 kHz/pa-48.0.txt0000644000076400001450000000012111320622144016662 0ustar denisitadm0 -30.0 10 -10.0 20 0.00 22.4 0.00 18000 0.00 20000 0.00 22000 -3.00 24000 -30.0 drc-3.2.2/source/target/48.0 kHz/bk-2-48.0.txt0000644000076400001450000000012111320622144017015 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 24000 -20.0drc-3.2.2/source/target/48.0 kHz/bk-3-spline-48.0.txt0000644000076400001450000000015111320622144020311 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 24000 -40.0drc-3.2.2/source/target/48.0 kHz/bk-3-48.0.txt0000644000076400001450000000012111320622144017016 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 24000 -20.0drc-3.2.2/source/target/48.0 kHz/bk-2-spline-48.0.txt0000644000076400001450000000015211320622144020311 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 24000 -40.0drc-3.2.2/source/target/48.0 kHz/bk-spline-48.0.txt0000644000076400001450000000015211320622144020152 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 24000 -40.0drc-3.2.2/source/target/48.0 kHz/ultra-48.0.txt0000644000076400001450000000005111320622144017413 0ustar denisitadm0 0.00 20000 0.00 21500 -10.0 24000 -20.0drc-3.2.2/source/target/48.0 kHz/bk-2-sub-48.0.txt0000644000076400001450000000012311320622144017606 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 24000 -20.0drc-3.2.2/source/target/48.0 kHz/bk-48.0.txt0000644000076400001450000000012111320622144016656 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 24000 -20.0drc-3.2.2/source/target/48.0 kHz/flat-48.0.txt0000644000076400001450000000001711320622144017214 0ustar denisitadm0 0.0 24000 0.0drc-3.2.2/source/target/48.0 kHz/subultra-48.0.txt0000644000076400001450000000007311320622144020131 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 20000 0.00 21500 -10.0 24000 -20.0drc-3.2.2/source/target/48.0 kHz/bk-3-sub-48.0.txt0000644000076400001450000000012311320622144017607 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 24000 -20.0drc-3.2.2/source/target/48.0 kHz/bk-sub-spline-48.0.txt0000644000076400001450000000022311320622144020740 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 24000 -40.0drc-3.2.2/source/target/48.0 kHz/bk-3-subultra-spline-48.0.txt0000644000076400001450000000030611320622144022152 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20100 -4.00 20200 -98.0 20300 -200.0 20400 -200.0 20500 -200.0 24000 -200.0drc-3.2.2/source/target/48.0 kHz/bk-2-sub-spline-48.0.txt0000644000076400001450000000022311320622144021077 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 24000 -40.0drc-3.2.2/source/target/48.0 kHz/bk-3-sub-spline-48.0.txt0000644000076400001450000000022211320622144021077 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 24000 -40.0drc-3.2.2/source/target/48.0 kHz/bk-sub-48.0.txt0000644000076400001450000000012311320622144017447 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 24000 -20.0drc-3.2.2/source/target/96.0 kHz/0000755000076400001450000000000013165107361015153 5ustar denisitadmdrc-3.2.2/source/target/96.0 kHz/bk-3-96.0.txt0000644000076400001450000000012111320622157017030 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/bk-2-spline-96.0.txt0000644000076400001450000000015211320622157020323 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 48000 -40.0drc-3.2.2/source/target/96.0 kHz/bk-3-spline-96.0.txt0000644000076400001450000000015111320622157020323 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 48000 -40.0drc-3.2.2/source/target/96.0 kHz/pa-96.0.txt0000644000076400001450000000012111320622157016674 0ustar denisitadm0 -30.0 10 -10.0 20 0.00 22.4 0.00 18000 0.00 20000 0.00 34000 -3.00 48000 -30.0 drc-3.2.2/source/target/96.0 kHz/bk-2-sub-spline-96.0.txt0000644000076400001450000000022311320622157021111 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 48000 -40.0drc-3.2.2/source/target/96.0 kHz/bk-2-96.0.txt0000644000076400001450000000012111320622157017027 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/bk-spline-96.0.txt0000644000076400001450000000015211320622157020164 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 48000 -40.0drc-3.2.2/source/target/96.0 kHz/bk-96.0.txt0000644000076400001450000000012111320622157016670 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/bk-3-subultra-spline-96.0.txt0000644000076400001450000000030611320622157022164 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20100 -4.00 20200 -98.0 20300 -200.0 20400 -200.0 20500 -200.0 48000 -200.0drc-3.2.2/source/target/96.0 kHz/bk-2-sub-96.0.txt0000644000076400001450000000012311320622157017620 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/subultra-96.0.txt0000644000076400001450000000007311320622157020143 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 20000 0.00 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/ultra-96.0.txt0000644000076400001450000000005111320622157017425 0ustar denisitadm0 0.00 20000 0.00 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/bk-3-sub-spline-96.0.txt0000644000076400001450000000022211320622157021111 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 48000 -40.0drc-3.2.2/source/target/96.0 kHz/bk-sub-96.0.txt0000644000076400001450000000012311320622157017461 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/bk-3-sub-96.0.txt0000644000076400001450000000012311320622157017621 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 48000 -20.0drc-3.2.2/source/target/96.0 kHz/flat-96.0.txt0000644000076400001450000000001711320622157017226 0ustar denisitadm0 0.0 48000 0.0drc-3.2.2/source/target/96.0 kHz/bk-sub-spline-96.0.txt0000644000076400001450000000022311320622157020752 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 48000 -40.0drc-3.2.2/source/target/44.1 kHz/0000755000076400001450000000000013165107360015144 5ustar denisitadmdrc-3.2.2/source/target/44.1 kHz/bk-sub-spline-44.1.txt0000644000076400001450000000022311320622136020733 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 22050 -40.0drc-3.2.2/source/target/44.1 kHz/bk-3-spline-44.1.txt0000644000076400001450000000015111320622136020304 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 22050 -40.0drc-3.2.2/source/target/44.1 kHz/subultra-44.1.txt0000644000076400001450000000007311320622136020124 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 20000 0.00 21500 -10.0 22050 -20.0drc-3.2.2/source/target/44.1 kHz/bk-2-sub-spline-44.1.txt0000644000076400001450000000022311320622136021072 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 22050 -40.0drc-3.2.2/source/target/44.1 kHz/bk-sub-44.1.txt0000644000076400001450000000012311320622136017442 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 22050 -20.0drc-3.2.2/source/target/44.1 kHz/pa-44.1.txt0000644000076400001450000000012111320622136016655 0ustar denisitadm0 -30.0 10 -10.0 20 0.00 22.4 0.00 18000 0.00 20000 0.00 21000 -3.00 22050 -30.0 drc-3.2.2/source/target/44.1 kHz/bk-2-44.1.txt0000644000076400001450000000012111320622136017010 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 22050 -20.0drc-3.2.2/source/target/44.1 kHz/bk-2-spline-44.1.txt0000644000076400001450000000015211320622136020304 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 22050 -40.0drc-3.2.2/source/target/44.1 kHz/ultra-44.1.txt0000644000076400001450000000005111320622136017406 0ustar denisitadm0 0.00 20000 0.00 21500 -10.0 22050 -20.0drc-3.2.2/source/target/44.1 kHz/flat-44.1.txt0000644000076400001450000000001711320622136017207 0ustar denisitadm0 0.0 22050 0.0drc-3.2.2/source/target/44.1 kHz/bk-spline-44.1.txt0000644000076400001450000000015211320622136020145 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 22050 -40.0drc-3.2.2/source/target/44.1 kHz/bk-3-sub-44.1.txt0000644000076400001450000000012311320622136017602 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 22050 -20.0drc-3.2.2/source/target/44.1 kHz/bk-44.1.txt0000644000076400001450000000012111320622136016651 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 22050 -20.0drc-3.2.2/source/target/44.1 kHz/bk-3-44.1.txt0000644000076400001450000000012111320622136017011 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 22050 -20.0drc-3.2.2/source/target/44.1 kHz/bk-3-sub-spline-44.1.txt0000644000076400001450000000022211320622136021072 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 22050 -40.0drc-3.2.2/source/target/44.1 kHz/bk-3-subultra-spline-44.1.txt0000644000076400001450000000030611320622136022145 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20100 -4.00 20200 -98.0 20300 -200.0 20400 -200.0 20500 -200.0 22050 -200.0drc-3.2.2/source/target/44.1 kHz/bk-2-sub-44.1.txt0000644000076400001450000000012311320622136017601 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 22050 -20.0drc-3.2.2/source/target/88.2 kHz/0000755000076400001450000000000013165107360015155 5ustar denisitadmdrc-3.2.2/source/target/88.2 kHz/ultra-88.2.txt0000644000076400001450000000005111320622152017426 0ustar denisitadm0 0.00 20000 0.00 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/bk-sub-88.2.txt0000644000076400001450000000012311320622152017462 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/bk-2-88.2.txt0000644000076400001450000000012111320622152017030 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/flat-88.2.txt0000644000076400001450000000001711320622152017227 0ustar denisitadm0 0.0 44100 0.0drc-3.2.2/source/target/88.2 kHz/bk-3-subultra-spline-88.2.txt0000644000076400001450000000030611320622152022165 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20100 -4.00 20200 -98.0 20300 -200.0 20400 -200.0 20500 -200.0 44100 -200.0drc-3.2.2/source/target/88.2 kHz/subultra-88.2.txt0000644000076400001450000000007311320622152020144 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 20000 0.00 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/bk-3-88.2.txt0000644000076400001450000000012111320622152017031 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/bk-sub-spline-88.2.txt0000644000076400001450000000022311320622152020753 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 44100 -40.0drc-3.2.2/source/target/88.2 kHz/bk-2-sub-spline-88.2.txt0000644000076400001450000000022311320622152021112 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 44100 -40.0drc-3.2.2/source/target/88.2 kHz/bk-88.2.txt0000644000076400001450000000012111320622152016671 0ustar denisitadm0 -20.0 10 -10.0 20 0.00 400 0.00 12800 -5.00 20000 -6.00 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/bk-2-sub-88.2.txt0000644000076400001450000000012311320622152017621 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 200 0.00 12800 -3.00 20000 -3.50 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/bk-3-spline-88.2.txt0000644000076400001450000000015111320622152020324 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 44100 -40.0drc-3.2.2/source/target/88.2 kHz/bk-3-sub-spline-88.2.txt0000644000076400001450000000022211320622152021112 0ustar denisitadm0 -200.0 14 -200.0 15 -200.0 16 -200.0 17 -100.0 18 0.00 19 0.00 20 0.00 50 0.00 100 0.00 150 0.00 19900 -3.95 20000 -4.00 20500 -4.00 44100 -40.0drc-3.2.2/source/target/88.2 kHz/pa-88.2.txt0000644000076400001450000000012111320622152016675 0ustar denisitadm0 -30.0 10 -10.0 20 0.00 22.4 0.00 18000 0.00 20000 0.00 32050 -3.00 44100 -30.0 drc-3.2.2/source/target/88.2 kHz/bk-2-spline-88.2.txt0000644000076400001450000000015211320622152020324 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 150 0.00 200 0.00 250 0.00 19900 -3.45 20000 -3.50 20500 -3.50 44100 -40.0drc-3.2.2/source/target/88.2 kHz/bk-3-sub-88.2.txt0000644000076400001450000000012311320622152017622 0ustar denisitadm0 -200.0 16 -120.0 18 0.00 100 0.00 12800 -3.50 20000 -4.00 21500 -10.0 44100 -20.0drc-3.2.2/source/target/88.2 kHz/bk-spline-88.2.txt0000644000076400001450000000015211320622152020165 0ustar denisitadm0 -40.0 18 0.00 19 0.00 20 0.00 350 0.00 400 0.00 450 0.00 19900 -5.95 20000 -6.00 20500 -6.00 44100 -40.0drc-3.2.2/source/bwprefilt.cpp0000644000076400001450000001453613165104476015273 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Prefiltratura a bande di un segnale */ #include #include "bwprefilt.h" #include "convol.h" #include "fir.h" #include "level.h" /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Calcolo potenza intera di un numero */ DLReal IntPow(DLReal X,unsigned int N) { unsigned int I; DLReal Pow = 1; for(I = 1;I <= N;I <<= 1) { if ((I & N) != 0) Pow *= X; X *= X; } return(Pow); } /* Prefiltratura a bande di un segnale */ void BWPreFilt(const DLReal * InImp, const int IBS, const int FBS, const int FilterLen, const int BandSplit, const DLReal WindowExponent, const int SampleFreq, const DLReal StartFreq, const DLReal EndFreq, const int WindowGap, DLReal * OutImp, const WindowType WType, const BWPPrefilteringType BWPType) { /* Array risultati parziali */ DLReal * COut; /* Array filtro FIR */ DLReal * FIRFilter; /* Array finestratura segnale di ingresso */ DLReal * CIn; /* Array temporanei convoluzione */ DLComplex * CA; DLComplex * CB; /* Numero banda corrente */ int Band; /* Estremi della banda. */ DLReal BLow; DLReal BHigh; /* Larghezza banda */ DLReal BWidth; /* Inizio e fine filtratura */ DLReal FilterBegin; DLReal FilterEnd; /* Posizione finestra su segnale */ int WStart; int WLen = 0; int I; int OBS; /* Coefficienti calcolo finestra su segnale */ DLReal A = 0; DLReal Q = 0; DLReal B = 0; /* Calcola la dimensione del blocco in uscita dalla convoluzione */ OBS = IBS + FilterLen - 1; /* Calcola inizio e fine della prefiltratura */ FilterBegin = (2 * StartFreq) / SampleFreq; FilterEnd = (2 * EndFreq) / SampleFreq; /* Alloca gli array temporanei */ CIn = new DLReal[IBS]; COut = new DLReal[OBS]; FIRFilter = new DLReal[FilterLen]; /* Calcola la dimensione degli array di appoggio convoluzione */ for (I = 1; I < OBS; I <<= 1) { } /* Alloca gli array di appoggio convoluzione */ CA = new DLComplex[I]; CB = new DLComplex[I]; /* Imposta i parametri iniziali */ Band = 0; BLow = 0; BHigh = 0; BWidth = (DLReal) pow(2,1.0/BandSplit); /* Verifica il tipo di curva di prefiltratura */ switch (BWPType) { /* Proporzionale */ case BWPProportional: /* Calcola i coefficienti per il calcolo finestratura */ B = (DLReal) exp(log(((DLReal) FBS) / IBS) / WindowExponent); Q = (DLReal) (B * FilterEnd - FilterBegin) / (1.0 - B); A = (DLReal) (1.0 / (IBS * pow(FilterBegin + Q,WindowExponent))); break; /* Bilineare */ case BWPBilinear: /* Calcola i coefficienti per il calcolo finestratura */ A = (DLReal) (IBS - FBS); Q = (DLReal) ((pow(WindowExponent,4.0) * (FilterBegin / FilterEnd)) - 1.0); B = (DLReal) (Q + 1.0); break; } /* Ciclo sulle bande */ while (BHigh < FilterEnd) { /* Calcola gli estremi banda */ if (Band == 0) BLow = 0; else BLow = (DLReal) (FilterBegin * IntPow(BWidth,Band - 1)); BHigh = (DLReal) (FilterBegin * IntPow(BWidth,Band)); if (BHigh > FilterEnd) BHigh = 1.0; /* Verifica la banda di finestratura */ if (Band == 0) WLen = IBS; else { /* Verifica il tipo di curva di prefiltratura */ switch (BWPType) { /* Proporzionale */ case BWPProportional: /* Calcola l'intervallo di finestratura */ WLen = 1 + (int) (ceil(0.5 / (A * pow(BHigh + Q,WindowExponent))) * 2); break; /* Bilineare */ case BWPBilinear: /* Calcola l'intervallo di finestratura */ WLen = 1 + (int) (ceil(0.5 * (FBS + A * (1.0 - ((BHigh - FilterBegin) / (B - (BHigh - FilterBegin) * Q))))) * 2); break; } } /* Controlla che non vi siano errori di arrotondamento */ if (WLen >= IBS) WLen = ((IBS / 2) * 2) - 1; if (WLen < FBS) WLen = FBS; /* Calcola il punto di partenza */ WStart = (IBS - WLen) / 2; /* Riporta la banda */ printf("Band: %3d, %7.1f - %7.1f Hz, FIR, ", (int) Band, (double) (BLow * SampleFreq) / 2, (double) (BHigh * SampleFreq) / 2); fflush(stdout); printf("wind: %6d, ", (int) WLen); fflush(stdout); /* Effettua la finestratura del segnale */ for (I = 0; I < IBS; I++) CIn[I] = InImp[I]; if (WindowGap > WLen) SpacedBlackmanWindow(&CIn[WStart],WLen,WindowGap,WType); else if (WLen > 2) SpacedBlackmanWindow(&CIn[WStart],WLen,WLen - 2,WType); else SpacedBlackmanWindow(&CIn[WStart],WLen,0,WType); /* Azzeramento parte esterna alla finestra */ if (WType != WRight) for (I = 0; I < WStart; I++) CIn[I] = 0; if (WType != WLeft) for (I = WStart + WLen; I < IBS; I++) CIn[I] = 0; /* Calcola il filtro passa banda */ BandPassFir(FIRFilter,FilterLen,BLow,BHigh); BlackmanWindow(FIRFilter,FilterLen); printf("conv, "); fflush(stdout); /* Effettua la convoluzione tra segnale e filtro */ DFftConvolve(FIRFilter,FilterLen,CIn,IBS,COut,CA,CB); printf("sum, "); fflush(stdout); /* Aggiunge il segnale al segnale risultante */ for (I = 0; I < OBS; I++) OutImp[I] += COut[I]; printf("done.\n"); fflush(stdout); Band++; } /* Dealloca gli array intermedi */ delete[] CIn; delete[] COut; delete[] FIRFilter; delete[] CA; delete[] CB; } drc-3.2.2/source/lsconv.cbp0000644000076400001450000000455313165106030014545 0ustar denisitadm drc-3.2.2/source/makefile0000644000076400001450000001026713165106622014261 0ustar denisitadm# DRC base makefile # DRC version VERSION=3.2.2 # Destination directory DESTDIR= # Where to install INSTALL_PREFIX=$(DESTDIR)/usr # Compiler CC=g++ # Standard optimization settings, with support for # default compilation flags CFLAGS+=-O2 -I. # Standard optimization settings, # tested also on Mac OS X # CFLAGS=-O -s -I. # Standard optimization settings, for systems missing getopt # CFLAGS=-O2 -I. -I./getopt # i686 optimizaztions settings # CFLAGS=-march=pentium3 -O -mfancy-math-387 -msse -mtune=pentium3 -I. # Pentium 3 or greater optimizaztions settings with SSE support # Be careful: -mfpmath=sse sometimes causes accuracy problems # CFLAGS=-march=pentium3 -O -s -mfancy-math-387 -msse -mfpmath=sse -mtune=pentium3 -I. # Same as above, but tested on recent Mac OS X # Be careful: -mfpmath=sse sometimes causes accuracy problems # CFLAGS=-march=pentium3 -O -s -m32 -mfancy-math-387 -msse -mfpmath=sse -mtune=pentium3 -I. # Athlon64 settings # CFLAGS=-march=athlon64 -O3 -s -fPIC -I. # Vectorization settings (GCC 4 Only, experimental, only partially working) # CFLAGS=-march=pentium3 -O3 -s -pg -g -mfancy-math-387 -msse -mfpmath=sse -mtune=pentium3 -ftree-vectorize -ftree-vectorizer-verbose=2 -I. # Debug settings # Warning check pedantic settings # Strong optimization is enabled because some warning are't checked without it # Remove the optimization options for normal debugging # CFLAGS=-O3 -pedantic -Wextra -Wall -g -DDebugMLeaks -D_DEBUG_NEW_EMULATE_MALLOC -I. -IMLeaks # Profiling settings # CFLAGS=-march=pentium3 -O -pg -g -mfancy-math-387 -msse -mfpmath=sse -mtune=pentium3 -I. # Optimization settings for glsweep # Some of the strong optimization settings provided above may # cause accuracy problems with glsweep. If you decide to use them # it's better to use some specific settings for glsweep, for example like: # # GLSCFLAGS=-O2 -I. # GLSCFLAGS=$(CFLAGS) # DRC sources DRCSRC=baselib.cpp drc.cpp fft.cpp hd.cpp slprefilt.cpp bwprefilt.cpp convol.cpp dspwind.cpp spline.cpp fir.cpp level.cpp toeplitz.cpp kirkebyfd.cpp drccfg.cpp psychoacoustic.cpp cmdline.cpp cfgparse.cpp fftsg.c gsl/gsl_fft.c gsl/error.c gsl/stream.c minIni/minIni.c # DRC sources for debug and warning checks # DRCSRC=baselib.cpp drc.cpp fft.cpp hd.cpp slprefilt.cpp bwprefilt.cpp convol.cpp dspwind.cpp spline.cpp fir.cpp level.cpp toeplitz.cpp kirkebyfd.cpp drccfg.cpp psychoacoustic.cpp cmdline.cpp cfgparse.cpp fftsg.c gsl/gsl_fft.c gsl/error.c gsl/stream.c minIni/minIni.c MLeaks/debug_new.cpp # DRC sources for systems missing getopt # DRCSRC=baselib.cpp drc.cpp fft.cpp hd.cpp slprefilt.cpp bwprefilt.cpp convol.cpp dspwind.cpp spline.cpp fir.cpp level.cpp toeplitz.cpp kirkebyfd.cpp drccfg.cpp psychoacoustic.cpp cmdline.cpp cfgparse.cpp fftsg.c gsl/gsl_fft.c gsl/error.c gsl/stream.c minIni/minIni.c getopt/getopt.c getopt/getopt1.c # GLSweep sources GLSWEEPSRC=glsweep.c # LSConv sources LSCONVSRC=lsconv.c fftsg_h.c # Compiled objects OBJS=drc lsconv glsweep # Installation definitions CONFIG_TARGETS=config/* TARGET_TARGETS=target/* MIC_TARGETS=mic/* DOC_TARGETS=readme.txt BIN_TARGETS=drc lsconv glsweep # Targets ALL: drc glsweep lsconv drc: $(DRCSRC) $(CC) $(LDFLAGS) $(CPPFLAGS) $(CFLAGS) -o drc $(DRCSRC) -lm -lstdc++ glsweep: $(GLSWEEPSRC) $(CC) $(LDFLAGS) $(CPPFLAGS) $(GLSCFLAGS) -o glsweep $(GLSWEEPSRC) -lm lsconv: $(LSCONVSRC) $(CC) $(LDFLAGS) $(CPPFLAGS) $(CFLAGS) -o lsconv $(LSCONVSRC) -lm clean: rm -f $(OBJS) install: $(CONFIG_TARGETS) $(TARGET_TARGETS) $(MIC_TARGETS) $(DOC_TARGETS) $(BIN_TARGETS) install -d $(INSTALL_PREFIX)/bin install $(BIN_TARGETS) $(INSTALL_PREFIX)/bin install -d $(INSTALL_PREFIX)/share/drc/config/ cp --recursive --no-dereference --preserve=links --no-preserve=ownership $(CONFIG_TARGETS) $(INSTALL_PREFIX)/share/drc/config/ install -d $(INSTALL_PREFIX)/share/drc/target/ cp --recursive --no-dereference --preserve=links --no-preserve=ownership $(TARGET_TARGETS) $(INSTALL_PREFIX)/share/drc/target/ install -d $(INSTALL_PREFIX)/share/drc/mic/ cp --recursive --no-dereference --preserve=links --no-preserve=ownership $(MIC_TARGETS) $(INSTALL_PREFIX)/share/drc/mic/ install -d $(INSTALL_PREFIX)/share/doc/drc-$(VERSION)/ install $(DOC_TARGETS) $(INSTALL_PREFIX)/share/doc/drc-$(VERSION)/ drc-3.2.2/source/minIni/0000755000076400001450000000000013165107360013776 5ustar denisitadmdrc-3.2.2/source/minIni/minIni.h0000644000076400001450000001335511707302012015370 0ustar denisitadm/* minIni - Multi-Platform INI file parser, suitable for embedded systems * * Copyright (c) CompuPhase, 2008-2012 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * * Version: $Id: minIni.h 42 2012-01-04 12:14:54Z thiadmer.riemersma $ */ #ifndef MININI_H #define MININI_H #include "minGlue.h" #if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined INI_ANSIONLY #include #elif !defined __T typedef char TCHAR; #endif #if !defined INI_BUFFERSIZE #define INI_BUFFERSIZE 512 #endif #if defined __cplusplus extern "C" { #endif int ini_getbool(const TCHAR *Section, const TCHAR *Key, int DefValue, const TCHAR *Filename); long ini_getl(const TCHAR *Section, const TCHAR *Key, long DefValue, const TCHAR *Filename); int ini_gets(const TCHAR *Section, const TCHAR *Key, const TCHAR *DefValue, TCHAR *Buffer, int BufferSize, const TCHAR *Filename); int ini_getsection(int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename); int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename); #if defined INI_REAL INI_REAL ini_getf(const TCHAR *Section, const TCHAR *Key, INI_REAL DefValue, const TCHAR *Filename); #endif #if !defined INI_READONLY int ini_putl(const TCHAR *Section, const TCHAR *Key, long Value, const TCHAR *Filename); int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const TCHAR *Filename); #if defined INI_REAL int ini_putf(const TCHAR *Section, const TCHAR *Key, INI_REAL Value, const TCHAR *Filename); #endif #endif /* INI_READONLY */ #if !defined INI_NOBROWSE typedef int (*INI_CALLBACK)(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const void *UserData); int ini_browse(INI_CALLBACK Callback, const void *UserData, const TCHAR *Filename); #endif /* INI_NOBROWSE */ #if defined __cplusplus } #endif #if defined __cplusplus #if defined __WXWINDOWS__ #include "wxMinIni.h" #else #include /* The C++ class in minIni.h was contributed by Steven Van Ingelgem. */ class minIni { public: minIni(const std::string& filename) : iniFilename(filename) { } bool getbool(const std::string& Section, const std::string& Key, bool DefValue=false) const { return static_cast(ini_getbool(Section.c_str(), Key.c_str(), int(DefValue), iniFilename.c_str())); } long getl(const std::string& Section, const std::string& Key, long DefValue=0) const { return ini_getl(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } int geti(const std::string& Section, const std::string& Key, int DefValue=0) const { return static_cast(this->getl(Section, Key, long(DefValue))); } std::string gets(const std::string& Section, const std::string& Key, const std::string& DefValue="") const { char buffer[INI_BUFFERSIZE]; ini_gets(Section.c_str(), Key.c_str(), DefValue.c_str(), buffer, INI_BUFFERSIZE, iniFilename.c_str()); return buffer; } std::string getsection(int idx) const { char buffer[INI_BUFFERSIZE]; ini_getsection(idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); return buffer; } std::string getkey(const std::string& Section, int idx) const { char buffer[INI_BUFFERSIZE]; ini_getkey(Section.c_str(), idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); return buffer; } #if defined INI_REAL INI_REAL getf(const std::string& Section, const std::string& Key, INI_REAL DefValue=0) const { return ini_getf(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } #endif #if ! defined INI_READONLY bool put(const std::string& Section, const std::string& Key, long Value) const { return (bool)ini_putl(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()); } bool put(const std::string& Section, const std::string& Key, int Value) const { return (bool)ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()); } bool put(const std::string& Section, const std::string& Key, bool Value) const { return (bool)ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()); } bool put(const std::string& Section, const std::string& Key, const std::string& Value) const { return (bool)ini_puts(Section.c_str(), Key.c_str(), Value.c_str(), iniFilename.c_str()); } bool put(const std::string& Section, const std::string& Key, const char* Value) const { return (bool)ini_puts(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()); } #if defined INI_REAL bool put(const std::string& Section, const std::string& Key, INI_REAL Value) const { return (bool)ini_putf(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()); } #endif bool del(const std::string& Section, const std::string& Key) const { return (bool)ini_puts(Section.c_str(), Key.c_str(), 0, iniFilename.c_str()); } bool del(const std::string& Section) const { return (bool)ini_puts(Section.c_str(), 0, 0, iniFilename.c_str()); } #endif private: std::string iniFilename; }; #endif /* __WXWINDOWS__ */ #endif /* __cplusplus */ #endif /* MININI_H */ drc-3.2.2/source/minIni/LICENSE0000644000076400001450000002504711414637524015020 0ustar denisitadm Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ EXCEPTION TO THE APACHE 2.0 LICENSE As a special exception to the Apache License 2.0 (and referring to the definitions in Section 1 of this license), you may link, statically or dynamically, the "Work" to other modules to produce an executable file containing portions of the "Work", and distribute that executable file in "Object" form under the terms of your choice, without any of the additional requirements listed in Section 4 of the Apache License 2.0. This exception applies only to redistributions in "Object" form (not "Source" form) and only if no modifications have been made to the "Work". TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. drc-3.2.2/source/minIni/NOTICE0000644000076400001450000000102311200251160014660 0ustar denisitadmminIni is a programmer's library to read and write "INI" files in embedded systems. The library takes little resources and can be configured for various kinds of file I/O libraries. The method for portable INI file management in minIni is, in part based, on the article "Multiplatform .INI Files" by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal. The C++ class in minIni.h was contributed by Steven Van Ingelgem. The option to compile minIni as a read-only library was contributed by Luca Bassanello. drc-3.2.2/source/minIni/minIni.pdf0000644000076400001450000065572611701040400015722 0ustar denisitadm%PDF-1.4 %쏢 5 0 obj <> stream x[YsĔ_2xAG"E#&y@Œx*?> ` gyH\sTbW ̛3q>[O]wv/B@>G; :7ndkuK[B3B@ NC)l.*/P>&U%3b7#jD 6tZc"~9~=_ž&%j ld'9&)Q+Yw@Bߌ^2, պ`bmlۡqN)*S)!oʎ~JA^^d7gA&̘MM>|@Y_c<^ ^Џ1(e6ۚ }Ժ9|Ы6v9nL럇1r|9#  Qf6Tx۬Pȷl2?;\7'ANV:.ަ T x.5'aU(5yD_zVyCXK,Sdwq.O :mz"ߛrF (> stream xZ[ݶ~_qJm,H "uOч 7u#P$g(tC7o|w'uOţ'p|]]|w҄C&))QN.uS߇ocL%m4K,8M1n<*5ͳZgァe1K7kbH簊U&o $0eVܧOGn~7A"4sbd5TէG2\ױgZEhj;?h˂E[:~rƲ bUfܬuI–9rzPLoi0)-pNL fK9mOW4jP P[%:S0S1N_]~-Mը6Dkf4BO& 7-!sy7)sMڻ2X G4ֲ kd,(iuw#ih?>.{)v+6k,՚)AEW VxaQNۈ40߈;kB5aIN'g\i;h-m6Zؙ1X/^>e5^PR:oJĿ/ID[9Ҟm sWYxl؉dܪh6*:K IT; ;l#6֖P~|J[#NDQޢKy~qie_( QȡcvPcc1"vj 3tKm1UݜX@c#ru2}ͮ;u~\\~P~=ZK98> \Eq0qRt>nTb$ȁ/+$WTpWN |p4un^5.3v4ǓbED|6/ OʢY%cv5)x&}ܙ" 3= Bݬtr&Yawwҧ1{\fjJ-C%%xiHXgy_KSm `+m^jI GeGŤ4i%WĹJh[ܷ#67/Ih[싹fxI@TIԤ>P=`򯫋0}ސYg 2-Pt.NDz 3%J> 4%Ԗ½W׍EGsg qH/wgI܏6uR]jo;:3iozET/$t|mBw, %k#y9m)ץ/vri畗ó !\Q׃6k4 d;>$W/6 (^Oe hs*\L :^qTӯdǜ ڵ^9qfEj|m8K E v+)4\qN Ԕce_UPd[/MBmEWR&zmU-ڶX-va̝ S0Gn9 ݦ(;agUm:L|*Z=깎rұ;_1} lи0c@#훉:oaɦEߛvzg[z*MWk~W5Xfd⸘Dĵ:}\E"ܝ[L4l6OY "vLk|-'1thGޖz=^ĢGrˤ$|ֹ L NƟ"endstream endobj 75 0 obj 2276 endobj 83 0 obj <> stream x][s7rN*/,SڇI ff]yXavx-Ʈz$RXE[j| t957+ۧͰH~K.skCNBu&|{klzgܘκfg}MN41|ܴ:0ƏپmLvޙuم4ff yoOCsқO@xrף77 iC0kXo?ܾ}Os?o}:F7)y:uV@a(?"$. yXFn<^G ̵U};y ~ *vmvORc7獋O`~ 9th` -l bB3a}ﶯCsxAT/~_a D4!W'P98nKl#| V` Ӝ6DZ~."F4?p R at508-j0'*%Sj=K7=׵ R; x C;YjGϑ%PIDD5d}P@_fA\2^iS]xA_yEovKI., .}V<(R7<Mh@eao_둊v4~^I# WR@Z1!oTqīoPطKFԱ.GK]ů}j[/3KzF\jA$jSP{QV1s3=f%2dG$&ɨSk~fV[LBRK'-v;sp85RG*l 2 ;W%@2v`},JOxAL@^aIc%ầOl\S_A!2PSJ0\__N GW6uLl:P6.e$F=%,B9N d4F W,l {->LBAXkє \_ $ėC5C$c[O =pE?حIZ5LjֶQc 猓L#k:֑ zx!:ۥƊ.Maʪ"u%SGh)W #u⬓bTL:BEO+L ԭ$.T"UhF1Z۲2d)I.nL.o#Q0 sE~&l|\fsZ粎|/;_1_|?a̙PFs^j__ۧBS@ʂ6_i'6جW(L I+ɶGCacTԑ8+iecsn2$J;"4l%D+"Ds&V(q[xG)L ӐI\j́*3>軝4Sc4bjҝWcKKgm['mG]O::[@ FȪHD PҠRVi{tMĥfFɌA`-Pq3Ngl#@Ha*$2|IRWJl[nN怨PNi5'Pvw. Tr5(9 /i4S%OΟfg~ ,|5ѵ:껩ͲCH/*|QT%iƴhH.;] ^2*}AJ хL3岄;$59e:XaolJ)aEel}8Ki!3}934 04IHm{ @"?ꎬ`…#Q/HJHcy!8oүx:gu1ӮI7z0R2 u7. %Չ6kL^^`dKw )7"mnM+a (s["Kf֠pGЉQvV읊?L]6: ZS`%wmV#̂Es&Oeدw4voԖZ|:3(̪B:K K3p8h5 4='cGa`NI|qcw ߺ&rD`gSG^4gn-$k$MӞm*1]ĉFM6i)FVv\ ۛ nc}G3ɉ%/kl8^8#`lV:d-q(tTxa@5+*q ~A^x:z1&`D NJ&HQDpD2 e;X2!YLp= M3ϠXTv\m"CRVFH>R Y m"u1YcciHKl0u&oaHSE|٤^hV50b8TC*ȅ$H[@%p^Ϫ O5Aã`b=S\MYO&tZ *=q8߃Δv_~CwWpoˁ˅h.K%I^Q?Ut?,,eY{j=U D}XƆuپrdxUB"=vc#R,/{v ;~2QW~fl7À`> m!͋@"RURM"UJjtRjwЂ=JW:ދ.gwyCDbn3q_95-Z+m$x\zvɩ(W?ci`J2A/YN2/PW-8{y{HQRZ*%,v񫅣FU"m^M#&:ׯ/D@'Yi$7f8RɸS9-Dd _|Žo_5(s`<|x^Tb/; owt*6m ~hӆn]W,0lӫ{AȀAR0wx;BdάQ;7p B[(e0mx|;oSݸN\qMw\0畀i_Iu*o 23I"T71*wЮԸ+瘻a f?ΔWUמh):r8bmcrĬSBĪ0ʜ1 TE? 9}=kt4 m O$y3uQ:GcSL,Chxb3z)ȺۉŻ/iBs jPt*Ю6eVZV$zkHTq SU {UWŤF8sw$ 㕀ō &G"7?-.t;%\̵zugW 3_W9[uv*0n[l/A(@#]\2J6Մp `-saf*; wTh gtײU[rG`;Q<\.0;p#M " S gW .J-/"Ye J'AeYU>`#mA)w UsjnFDR"ʇh|tnA9ß[M¹RX*\a1΋Ƭex+'(щO)RV/ Z}z_LT iN/i[5ݑ*}JòbSXб#iĕ:IQFk̈`%%ToR|js]e$iS,<fD&AZKJ2I?/a|6GŢfIXwLt[Tyd0"T "YjACb} Qg !n@c: k 3lHut+j"]S-ypI䭂E{ 9R#!\nFM v1H^~'aa*("(_VTj}`Z?ÀO7+GBY'Q}gP\S쑽 XesNUE-lRqͦ_gP)KāEպ= &Yq38`:;Jvj<O%M ^EKH*$V ,5qlk'8֭0^ ^I.σ锲t ZSJOijyoZ;/C=0\{-a ,*ly?IV a"[EHa< ՍDN,n'Se{G sN~@:E(50s':g#n8v/tJ'J?S>P)STFoL Ї՛F*2"(%(i[×4٫ٳx+MLAסST$Էɓ?Er]c"[.+Lendstream endobj 84 0 obj 6181 endobj 96 0 obj <> stream xZ[oG̊3wgC lYBb)c6񩪾UEa2nKuW_]|\X/>8]q> X_{0HzhgՃ_;mg{7!!a|0Co~7fG5v(-?va-]Pu/Ժekkq7an*mviaGw} ='Uw q}!aQ˺>b${5Homm0MAzw^xKY@Z^;a}cs  ɵP8Xzv@WZzXJ4gp%>[X}\k,]n7gq2ǻOWoW;j_㟟Y=]؎Qpdx }7AɈxM<6en| YT׹ ;޳_vAe.ʒtG@Q#h% i'sa2t]N ]ptc(}p4}H2̇e`QLD9qQ\ ZBerWesiPZu#+`x;Y &#~w@ bɃb}~#Ҽ1p[f׀vȆ u@ AI `0XXs!HW#$ 60¥$qwޒ4BZAuφ%-/?P1]9l%k$duQ(==X+ nU| GE -J@ɒ> ?` Zd /ȼcTƴdeCw3z%' 5wYS_/2nE}5ļ3LS$( zɡ|0#"ii|l ^dSI,”8uv[ôY]~JV_HK p)v Y?LtXeF:5TZhx&) L\"Ӝ ]Ю)x*:mF*~`PƥXLEoa5|`S^ηfnѸ`c'L 澠F>MX2 T;B63pG]9prnKs)QMB΍y]U Z~/(B((LC'r10O|_:_1[;H*P9:NG/u.)3e a̻dP1Ú9$|IJ`&`;`j1 oiD;1vt4Q.Bvy# 'َVxbBLtG: O(9.;u"dA>iNڤsb ͨ`J4F243+;oCcewHN_Ln.@O\¨-[ڗFjz`E e,xelYbƚF>7K吘p; )U,|^Jc] `6کepqUr0%mV`.]&%UK o!B KťRu9ORzvcNy"Z"7)]yzvveFX99"=*巵=$*r1:Vny Q*&8)_(a' <~A񸌅fJxpSGY%&u3O*bS`r[>C֒U1jjoBYDWptWl1ㅺbd 2g{ҋ)cMþ /JY?/HxcUJ0=tb~ 5ݩa OrѓIEqPzKb>~endstream endobj 97 0 obj 3114 endobj 106 0 obj <> stream x]ے7ruqB=ubRU'BK[+i؇;io7/ld&2@zz8#CAB'3O&wCov~aU37__>;7)^a1'g 2f?;qyw0Ϻ1~üe?CiwCceV~y |McyQt[:yq`聅2?;Lu6Ltjv lԛi^lfڿc9 l޻y7Shqyx-LH7i0/tΏnY>ю~7a/q>{vwo^}|v/;svϾLyx-ȔV~ ,/R &.cN]{{+Mutdڂ8BO1J39u|ChJ14>xʠ$M A7볘efAx!%6?;`̂a/` jKc=|{ zæc-ACu>'H#[q\5|k$n6)H3cZ ˫˕ޟLQ:T S?-Unv ,fQgj?يh+v(LdAV8qeZYڢl9QN%GD%źH?:˳c6OeXwJמ ɕd'|fȭH01(읧p8L%>ؒmߕ ƞFGI3*zv"?q%x#T4L?~5W"_dʵg$E8*Q7ISP¥h@K2IF؏)ZHi hs[2 -!U()CBR00D2#86}^"ILil:61 17&_?~?1x< FzH,-OB}і7SEZ!8)GJtO)9xN4f~Ebȼ0IUCB|}vEј ֱsG-mJRJUuVfV*jE-"]+v_;&!a#i,9)YS8keSf;4KԔdF y.PJM&ۖeJN[2Bhҗ"\.RIuR]rXrPGC";ZaonKUaVlI}5",. u/U}^P j3SA4Ǣ 6yc*BnIjG @Y&ieY^'U"ҽȤʔD&2`c\ᅭ/8mL[+qIOC>xGP\҃ܲъh iJMR6jAix8҂eXvۇxϴ_$'ip0#EIvELL"mWFJ5ؠHE9&fU]ÂS AboFgsyfGCmD ֭)]-Sx\@RkN(0,& iSRCQ 9 F17v5\"uCr𸕰uPN p@6V-Ԇ.1PM:b!|L"܉}ٍlQUdKf4XofR̭"t;`}ksWydl~cZ3s&OdV1ι?Pմp}#?p-]rCwPSm¼5v% uHɚ"h1#q\%jh^b'ʎT}.c2! K4kF(R: 깐pp} БG̥} U֡*kpħn[BE@[cHjR ({\^RP@|@I-'V$"SJta05<'. EXł̾*U:lLiXTA$(IS?|]xդnUbZ/vY*'JF߰@oW'JKSKZ$W;.Yymap.i*A&e^&[$ Vd[P:a(k&8pD#*^2[MK;6;_j'츪JKS #!L>Zal X0Ujt6;u>*ID96@~gc9o"6A߲7ꢳ|W`}tQ>X$䈗޴iUe;6ٵ*kW-Y9ӛ& B# 7j3t뭯'޼dB T?=[p1 ~x٧m'% jhE,LUQW|@2 Lb]smRW'吟1()6GNB`ߊ٢f {u\LX&5 FX4?<9> Oޠ.AGܠܬ]"S*5ǭQ8FEK.siʌ)/wg~beI _ȨÆjt"3.9kWɓ]ۻ?By?7)k X:N@#<&k:US1N4j :i<:wl '  7:^)Z9UNv˧}& *DŽl:%wiON@)V5x'bM3>{~vZmN\CnlXlz:Wő24A(ΝhZCr;/ kdٮviU/VXTů.M00\xf11ɂrE&f̕O\ʒ??E&T;aS_ҨOZVML9qKYl$Ƶ5*w/γޫYyCOWȪ* ^-[YYF/r wU _bCoSTkUٮyqkAF6CFFDÖ)+_ù=s팉Jr|i]-9?\YɈ%IK;r̔jzGJ][֧S$AL㔉V[į3vi,s7In8P5MM,,y#h~ "08}".jLz7U(uyts p>mmbu nJITH7peI-dLfu6fA]}Ʃ2k+ӦRoMnoS”%R\\斀Tư0P()̔|RĪMuw3/C,W1rhUD>Ri&Z5|0ҶV]|k &ƕGpT&Y-Os}{YQfKTb 0vpS*t髮Q45Mw'WR73yШ '@TVL(L6IGu> stream x\[o}9-Nm'" C l]lKMwfH R zij^|[jjd_kmd?ûwM蕛ow: /8C3<|؅n/a~0/;׿ ~ 1 zWUn5x3⪛F^AտݨyQYko:]ꭆvLø4[Sen5~$s08!*z^Y=XX|[YA84b< ZY'@KجsnVCXc g6͉(fzVjZez?idƈ,y[F@k0Ή4ޫuƓtt `c?:1t< {{uux?Vjw_{ZfyPSY>8^(@(dC2x/OKףu]xk*#z}w6ۣґicG g݀¬?'Jvllteww+-};=~}9 ox][wp:ʡ#n.7q& C&Mb~Bkw,:gI+-deι]tButSSrczN$[-ii.HjZ /)|FPRЏ_7#+ryO˗+|柙ncE3@+xZ7n_BYamn@bjXyX ?+AE͊/W]w65M|b?Zbi?y/X }[$fBck/1V+{byD5Gn7?XJ龫;AHp_w.C%-i-]HR8vx}*u_s}#>|f陙&/~eaNDÁ*A4CsK]n3Dx0-(j-JZ@.d !ANG o:NM4M~؏&U!p/M#紌44V%iBXHb$! ZUM^OAQ2Ktjl:M34hGuO "[]L/8&=Ўpj0u"yLh/0Ԋy59?G0ĸjp-F$"E:S?|4Eiy "jƿN;QHD$J1KHN%c'@B+xaH/FxS!YjUP4\{!v+-FeEwv: eyuisO,IUYm7;x+n.o]9cs%{?D ǵ¿;Y­\{& I;0顷G A Gsm1|و}h,NU#F" AFjw`p)e-=2n14\t(4n$ZEُwX*u5^u}_ףmt (SwOUBes1ٜ 0s)~vſ-^Z 9@u& ;1,h[@d o#$D"mqB`V$ڹp'QVեf1xJFK H4G)/Ve^X%i$?wPɤRl,=3벳EdhjP܄Q;fzёE[r˒iY=Xűq8UFzgn7GR2"i'r`ɩw{N#7Cta5?hޫ2lLc1fPZXv%IfniZαOT!teÄ v={xT C3%$[KpiCvҰ.:<-{u"?m^_VUUgsI ƣ@}"b'IEIw+TopvpL l eo2CB.@.iMǷ ' ~,%[h3vog-=i8YRE .gvZϋ&~TzϤ2Vy3l*5MyX9Nn :N <#/,z"6WH2 ؂lʽ>¯DKT.`ga讏Q 4I'AWoĶk2L'a Tr(ט\J JT21D칶*7hUȵ 3X3G 31Y?CHO*9/IQH5-BHuvMNأJIJF]N9ͯe:or^r "{~5eۻ)/"O_T7~8M\ ti:zҤh݇ hz3yϖ&vT0pI>X#7:71vbE(~A7"gؓj J%rV;(@|/0 /R,=v _BU(ڇa+ S;NMrxXt@?j=KND01XnOaa SZFJr444yyҗ\t@I= 3avR9|RTbM-y.\\e*)g<[6Dg9gY]5,Y3cJ>OsAk@@+x74cW:H#~+؂DZ*Va(;ȿv'6-sVnuJ&;9GW<7!6[xf\,vukQ\Z!bT f;I+p,$hSqfrnm31$^z˙D,w?׃J&%q%W,9H($[( *_X ˚93ݞKs=̟evфc cZWq.>Q;GH1dUGy us^Kn}-~˸+K@`yȕ@γx')unca2V.Ơ%$ǏPl?Rh|]\|>Wr\|~uȏפ{~u>endstream endobj 114 0 obj 4718 endobj 119 0 obj <> stream x]q狀 vlp1/%94eQT <{/Q=]U]={wA9Guuկ^W]kV/}tzp:~}Э~>0*utQxiBK;wY=z~@_wS;8Q1:3_4}xݸ~l\y׏7cx>n6vل>桟og˗ᣡoi\:ziΰQv)r. ʄI3s`XFn}E i a 2GnD N.h%%ȡYɕb N[M6RHB0Ycr#AS|N@z$G'.3Z9n x`3:?ؽrrqU"}И0d8f$bI^;g{V #zFq<-^eML2/[|Ml _RIjE0"8H{+VY<[,'ۊ>فA8. to慱L0^iGM7vTz{$U?@^`$  v,~Rfb2vF!NT6Bܞ$M6>uZn`M2Z_=y8Ͽ#C_~S$Ef8>(sx[=NUsM c@yXy狀C հ.`ґK;WZxB z PGl.j6UBqEnm4WѤGcPPr Df x'5<]3Aޚ!j6O"ɂlk%T9Ϩ'$C&ӱ 8iHDž74\.:yڊs9 \hIim.5bJ ~/π1D!7 `|Xhؤ 2e6p xJ,umKGI m'0o5o@C@3tXOE+E&4.pmyW!,bK[f30 3 Hة^v;تu)O-7M2'"(ͫneen3 ~wwW]wrɆq/SM_駝Iuf,3a˷vn ȅѷ xbsZ}G%Tm~,ٶIX`*Iq'GԸ!_JW'f{..jXkK£P| C#C4! V  h-EZK.S2."$<5 lre]E23d-II2Lr#G s_ʬNl5 rR!gię2)L{5|tѬZ]ŝxw <+mq-ɴSƈ2^2I΢WFL;$޳0+r5M^Xn1Gz]\|DwM p^DaU&nɧ@ ,&tqFAOq *Ӱ}߃126?6O Z]f"[ל*Z3]vÙb<$U+TV+ag;1'$I |-X>cg;0O*Ram]v V#HޡKl@/9n[:I'.Ы{Ac&y7TB]t)/8e2'Z y4" jAb::,_^j|Y32Ic+O/2ssx6Y2S$9 DTb&*^u&MB{5N_7 ՛9n=-w> 焫M2iTKoq(klD|"A. E$]+gbJ쑼w_ Z-`/`(];cς̯&˟ƪ2}t^yfA~΢wd\(CXy`G5; MxPsn:3V -C~䦇tH@%?|A(霞H=Ķ7t`?xۛYUד媞y䂡&0c鄛ΤXn ޕ#dz+O 0M! .镼X&5/y}>c|4~)O)'~/eYi->d" BHo &# pu򸇧ye~I\WMV@~ AY_/$+kЉz `,͎ Zp"G#( F_M-s;t%$)w/\·la&_/<sk_)5 W]Q rH>-cG&Z_ǷYzM/䱊c5P+L4=q2-- N>Z(l ܜkd3L([V~.pS*|*[P53 _rr4ުT"GT{?KP4QP x@S# V2g-$yrefx U]Wfq,=4iͰ7Bt%rgBv#[_/|m:'>=߅7))7~ьLNϵڕg iI#ű/(f5\~p;SY dą0=jSQ@!IG)KY1oTg~^O),x:~h1>Lw}i⪹>&˘(B?YCJ4 fnhE~Gq.vOvDJ'%+1"ztJ$;a9Y0My :jZx|oC:ݨW/AIy3E|ĪrDl(d0,5]Vm o6iƏ5(yq.זl_+ g U9+<ǵD?cRn*͏(0/*!Xr%pM+ *qxm-NwePҰLjIȱ*)0HF1I֜_fL7p-/W *!WR95 p6;OE:cFWyd̦IH$vEJ2E `rJp88,h8Lɍ%~T ʎ.P['y-)R@й6۶dme.=o1q! RMlQ9 X㝗'KR/Ă 7PDj  sK$pVV\I0M$)Uo_ǚRD~>.^'Qv(XP=6Jn2pV@{/GR _.F?Iz*)U;*ȍjhG)w'3S"yD 4G}-t?8x,,ٗty(J]gų∂KƓB2>.fB[3dB0 Bx[,]d_Rׂr쭴)"tN M2btNMUF1P~ 䐊@Q]KWBYLӸU2'4=9>Uբm*@ar{Y-|-uJ\"I-zN#vI[1xMd3岀2g}nD&J` a%:*%eyِd^yM2 eUA*}*:ݔ9ɌH;1ի7=N4}T;㼉s+){zxΥOʙhxO.gXhNR^+~\.^v3~Nγ,xܹU.Y2^G5o̪r$A@Aa %-9nqy`@Dݣ+IJ.Ф򱊿zJ`9p~7Oa1+I"l>B1 _V 7m+r>(P +EԤOKj{) Gs5ҥ'V h{g1:|:QPQIaP^X$親.+ KΛ}[QRw~M.Fb.jcحdq:vYR/C䵩r0VxҦ[XaO9<ЂLwjo~OߦHo\vUrh,JΊ-Y|vw4DQEN;Z%䤃BjˀW M ?}mz?o[K!7}[z<C2o<[J_,^I" Zd9| ^A>Ve/ɪ Bat`|$/٤X :k ,?9Ss to#mߗ ֡<-X&0lF+qZ ~endstream endobj 120 0 obj 6226 endobj 125 0 obj <> stream x]Yqvq e6>& *PX\,XwefeVVu^A`<6Co6~ޣiѰ:ݑ6鯧7_ƛWeX=m6C?Ge vfΣ~ͽ ?=Ovl_v>>4y;v?ݱ {_cj&):Yyc;f,/H/7fY,Aw:}`{8n/wX췯1|x .}'.]Kҧ~MpwaMw<ǑvvqL=PoGY 3#'xw`/DWس8[Eƕ4=o>z0!O6Xq9yjur9;[H: ³@pOeM0~Ú=0ٴ=,N5F'ưl79Rage]']ZZr475Tt7}^ v ˆ&q鱉q $"0ϥ. J#;\qTCtCt˼ ӈa3#z۸g?XG6G"owL}9.\s /$dG;x'^E jD=Ԁb?;!7FgI;ul|dY2FC{xB9#5\T|7]WTo5:eԪ!ʩsaMy`ɏ(svY j_5.11zӱ̀Իw. Z'Q +'>B氾旤iR1i7@[Cz-/T,_GZLUӯy*e&+٢Gf;BELܸ쓷>&*/]cYp7y$&f˸<X\ x-*<4dpoW95'/v> 3Ћĵh hVˊU&N2+MVrq>M$T$(n#"q^ s{㬕-˱@@ cs̜ȸs}~5bČʈ xN:\xQZ;v6z-b9a]!~Jq~&G ]f*n-ZjG|66e|xhuʓ0JF'E\ȓ4jx5z`ŏYk#%,qL+G 34paR\HgRCk~\fQMrq$#+ݩ/31!%V9)9k8I LQ3W)9sB`uj.(A݋& 7*&?W=)vD!1D,fbu"jCp Ah@Ȉ8HTkrf5QlEF%3SD--ܴ w KfCt&_(/߲%6L#JEi*b1& !d&1L_wurJfR{'!+q*Y{ki~/vED}DԐ@:W ZHg- BTޣB;a]F=+QHB2E *A8N5wW|—޽Z?6ݶ,I3Ё`"HxTMt6,L2;CPn@z+i^vi\|Ymp$%vQ.v9v49&Ɗ*}:(Q@ '9L30w9n58b$U|2^9e 4 }`>Y" '|&1-qU`?iyd d2)v72?%C_u04(k\Ci"IwGküNayz/N|pqstC??|&b{"I4HQ#O R &zcx^ч1itS&$C5_+_z NCt/֗G# 1Ob|ѸF/.,*ʙ|&3]<{K2QeI rW$.c_.Sc^m&ZRBҰ @N[uH$lKmpl~㡨nmnۜ*lU~_O+2?wii\X$4|[k)hPT*L?υoyC(S;+J!6 (X&%NN>^I,(]UQ2 > YJ|;,b&I1/գ/.ND]g 嘚Q<p nD˜]gʰQ KsQ> T[LspB"uF  D51c&R;8RlJ14@/0XU5LN(]?-sY5JNa35b9D{|nasDZ3YPz) yb|Oםj3گ#z+"sӛg>Y/`EBA_`"f{_+0M&^alFn69_O9U쩆M)3AU5ZhX 5+Tpp̒KJQ饃K9fڟWqŔJo9).˙5}2Sie7%gT)#$R&b{ *{Ғ+*t}%=q5*fbOVMg:̨_Fץ#bĨ\5>ͣ, >):j/tg)-DYZb[ '}*;a#KQ @'>`)L- E"9 EhK_^[6ױ \3!& P5<;JγQP7 ֖Ңt70fUiWXV_Ly9YbEì"}X71FDNO#| 6k>BT%8 UJ]l6-]岽#3YY*Ok^Uj.3 $Zy@N S e!6| #7%s="s]چST QIg>;*5bߔ\J-Rw$FՙC3ߑxH}7;` w_ULߩ7# pV⭑R.9|K {6b ̴LfqzkYjٿǢ*56( eW^9U|L#\+k,9Vq5۵Uej%ȺY*a!ڥϮbyGZ=fpoYF)Y:M u<.Uqb?YPQ:TxV$k6Hi!7^vr xU>0 Y}΄ xfAya)^*C-*-h5r 76u#ϗGSMі}+߇O>^)/E][wWLc])>ރ}vͩkpe[xFi<_6c؈7 aqQ͖xpJ_ Kg,5čje0==춉Y,Co9Dfsaū'[F|([f7nŧ~$Jo,S '"wqiwŤSBZV+LEJݘȡ=RPCK(I[/c"y[4 wy8,PmjKXa\=4KEva`ey J'[JW*"YiF_xQKł*K@^*$+gVW8GuJ>өq3{)sׅ^*>T?,qFϥ*w x jm F*=jXlv[Vq="ݪ:lڍܭSYr;eiιpvᾠq [/A/m D* B4uSeO]]Q?]"t*"R_Zbga+UJݫ"(er4Z)q2vI@)r,KRbfW4!I RF 3(zh+)-e%|wXf Wk%zs4З,`sQhT13h `F Ӣ[xL^[40N ­Bu aƂWS3yo xߤToo$ߑ^IzL1+ Wo]BKӊ瘑RY7|U4T=J{ nHL;-k_,o] bT|_#yiV %j> stream x\{o7?C ,0ʹov=`}d}6!lZY#[z},3I?^_oa9X=:~F:<=H7~_^nqnۘ`a0έ/)~ O5B'QMg*3:BgFoX4fL;eGs恐 = T076Z qνJX{mWNmBoV@'? PmHl{=󋴏և8 _7um`πּ k"~܍c0.MlB/\ca} 4\w ~TXq@ lFG܈Ģ8Xoi.SO=c5uAwmo;`piN3hp JIVw84Q#2VѲ2Kmgm9H?Be)lH$ 4w(PqTzdvJCW95@jk\IN> nC#e`,j:BaـmNbT#5H.^ يVX`k,1 L F;i h wTl0m+ښ/XVod0O(됤xF<\묗u4#J*oqj [D>pɞ }%sa"=>ŸXSݴ_6XFi$dc##Gg:8>mب >ApӑVJ _$Օ}&mGz^ZRTCw(a0WGHx9*@+;-$S/TZ[ S噐p;=w]$IN°hq^U]GYAF[pudI{UdWS!9{nDH+r@SliE]>F>,x.5J By>Qsc#1 T iL|jD.h@p7dDáaCCq \וa e~G2lSCi<ײZ PXVqO 1eԊ?g6.E>UE'$e<=邰I-.F9H~>d.!ȥDG%"ƭvMjC+$h٪bC#-ڳU leDc9$sҙ$mv!Jp(-ZDRUC02X8CI4{Iu[k}i%GI%02y\o1x%9̨D]sQ"Rfg3.w["mZpѵ9f,ᎶD-#wEt{ ͊ 7.:B y &y 57b ڛ57>imq'!f0ihl`jfhGִ֭dRM؎2?#' K . KBx5GNS,~0" jz[J "`4D,:\R^1*H*ڙ ?+K%`mx8>ͪ];4#;i!Ċ(I͌CFLm\K!h#& JH $ ?PQ^i$vJX˓jT @3Jd3a̢b[\LXb%v n%8 Ɗcd$P+뤲(0Sc*C8$})2..x Zdհ**Eb:/Ld ^͡DxKwzQ`%&ƻXK;ּ1J!E!3 T]\vS JC."bPbTQ<*qFE@G$N:͌2 LOd8KNbޒ`YJa}R[~ip5HIn0KAh]sK'sj:9$ ohJ?Fi8DhC"( y"r!TvY[adn xЀ~*}!! 8GU:Y3Ko!U6TmK 4KFX(M3tNf9jA\),J*\eG[s$Ck|jAʳkQ4XNX[C\}[TP!Eg뎌ɥ:CΣ,mˇ^ !vNUkxEP1ܲ.~MY~3#oJ/ ES{$@Ͱ^$`s`Rj-WU4Nn*YRٓW8tVƛ@6Y䁇 kGYv#l]m>] \Us\+$ҁEx!thC_5my8tj{C\`yzGc\*pԆxaQVt*p<+:ӊ2Wba ewXxǿ_yv:x;?Wr7wi,D>WƓ7¯3/˯󭋘 *Q-F%( hIz SɞE8AdB1I۞6ßBcԘzpbp YܹﲭD$XNg Ol6<,Y3RHr14i "*.UEO(ۼ,Rm9ho\!9j 'Xw(FR M5o@[ R{-:_EJ}Kgp[L;S.2hp "W5iIC7=+hrMlCFd3pŕ[$bv 2l]e<@s2>I "_u.hF mM#Toa/FPlS~fTN2) L2Pn=`eY }n8@h&WѣZB)|/vbn}):2uF;Pm,kTt/s’s٘C|F=m:ԭImM/ AQA?nVqLʼnܻz5+~Zo~ qѷ6 2aqժݞ4wvcJ,xb;d!nS(NϮNɡTM^#H&7CK 3+"] A),:f 4RqJ_ {(p5#Wpo #AwӬ$2Q1Rl*ͶzxX 60+*C"cڥǗ 4::[eP@N[n9ᓘ+T$yʙz=#g5T#TԷ-ˆQw?D_%G,wzQp8wŚj6Y>e†P< 0qXeq .@H<o6]'pFW@#>A)6}ehيJx^a8& TqJq~tEa,!uyk ?ߍh\K?cJ%7,Mj{וagA pЍ<q"`0ԡgA{5do~g"dierRޏPJ; كT.Xef!Ifz<t9+mODpЂ3TjeHN~ 5+h᧑dG# {$Ю$5Zȸ{շgQtdbvMIOV\Ém;p e d MZAiIOnv(^EĝW] |)c2+,j/LkKEɕ(th_ү*#wrV$A$Mݧ{X*{`[c4́cdO{=ryvQetXx?/@ œ*YِV }boK :ߔ_ho"d1`} F^\_wL; (İ4,}C翌*T 5"KZ7?y2e>j$&_)V}#59!Ӎ NyK|1"+e;\BGhd5s0 q8971]A梣 iaquJFGa˒65̹.\,"qQQ-> stream xio$5~Ĉ47B® R򱇵>W׫WCջЋŀ<|o/w۝v9<]<ރ~F{Vս_8mzg{;Zn5Go'z* 3zXw+wr\^u~y֭İ}?4L[i H@NgWr $)z`Z`7k;Yug :NJ4i|/VRj{x.MΤJYQ㙞|Be2+1zg@&,Rݿ.Ww~;ğ}γE848V;ݞwvqTneG/0$X0[V(`osx$H\Iv@Q@fDAf)^@#eq#<:5B@q'0vr 7Wv;4R)ʂyÓN.@ L\+RAgp D,5 -nUEAx (Ge y}r4$@EZ,N7qr"J|$t;@ $m#%Iȶ>NO!+5PvD2d2"  "iG$6¢Hw$ڟ-ZEc:#!~+-?_us3SsJI=0=-?K9H7P$Tiv h~ o }Fd:eg:/tačnJ"D(/\>g{َp a&+3 Fm?aҐ.JfFLg#DV_;Aזڹ*7)K*rD,rh<3T f[ȠSi$(2Hd GC;B.Q7i׉u3@sGdޢYp?/3_p}&{F-ʁS5t%(XT̰s% UxM V w/˳L(ϕ0&>$h*Yhʍ$t*"6HٳRJ36yW*Σ@t-QcZ⢸RS8[=ӝxc53>x(GOWUvݷ%D 2_㔪-Zr.neD<@'CzѮPܖ,g4G+gIF @olqi 2\ƺ(2<+ͳ7^s37fya<֓ºs]Vc+;j>CT9n * x&>9:H0Z0©GߍBM7tH#!OFv MGHbYB~KO^n%#KRF i"*U؉*=}d=Ģz9j'kI?_̖ eEZ mR^"2m㭾\;.C4jHH^eg9dq :,:/զ$cjQ Q`u򤎸LŘ^Δ8L^}?i-:A|2YaȚgQv+l!gNӃG`z $׬_j~RR3H9qT-FnDG"K썽c1YiʣN0zU`HN泒hJpĔ垦N ] ۘV) in̆NSM$ԀD4J9{{ƙpPt;B!ZYYb7v)325HV#'Fb(Z%889BC: [J<Ɯx<#1(J⻠Й􍾠?)^E:2BcK4;wrX`n!N[C)LΧ-3^(X6E6>sytF!vsoNШ+fV|C?a=D::A|Gy2MgICyj2ދ<: Zy 1 VNث0zzp\~0nzNx"sD9Q~qƑՙuBn-dM Cns+ݨtX\hzр耀 lw҇e0і4wAL:[2>/J?As`9Ϯb"rtΕi9 Uenn)LU 6Kɥ1ӟDh]:a1@~#y$~xfC\p/tqV, AmpbdCUSt1QƩ?xh]:u$RTaz6&Pe2`dR8A] {> -cv; u!Nɑ8<ϓ(D{(du' _ɯ֛eWer8)7<º: )籅o $74>OR(;,<27lì7M;O؀)FN %z,\ "!pXU"gmQ7l`JK{?M(y|2FEBIotۭupm ZNftVf 뚠v*o&4z{Q:O}8# Ú`RfʜA3sT t"͢:nܰm@}R$Dy3&G(Tl+%RY/'_!ۘzCWkTRFV jAȎ*rXEzU7''x>rkmc` Gv8e>g&'"rVv sq W/nC\Fq1k;IZj͌4e߰eWBryy?/xGՖYӳm eZend޽7/⶷$פQR5K(۴Zꂣ 65RwQ$1S&dՖ+,C,N]=ҫ(UաrQӬ-L-Öv> stream x\[oK_?g\}h8u⢐%Y5,Yd%qߙm9G%7(zKsn,^,/}pd\_ ΛA,_!gN? X=o~ЋQ~ӝ/\Vb˿i˽ow,-ҽ[id]+{aQ>bg|=zΗ^WIə g \uzWfyҭAZ¥ <$,_#)a-y?8|Bi7L'BCXĿqױ%W6*([Ť` ẞZp&(s'PZQI/w А-M xC㚆Qs^[DVp CM^^]|G>8rpa߀9 擼$Z1lwhUXJLu(WHk $wx) - NL?E~ps\,)Ȥ13?YގaqyILb락O~\~qdqh-MX-3 '?@Wf BR$:1-O ރt,|n^qLSތ|xmy^&?7׭C=I\QkLv/ ufmMjPJ%lx]gU<ΗL;櫣-vw6z}mE ܎Ә< f2HZƑZ<\b /QrPڑ1P8;q1ġwǗ8,CuYVQҘo0'BN嬄R|FYt^R!18-]!8㮓@A'^jpG>JY(A0n[UO# {eL ϓVigg޶Qhu.f!$_&jd-*i`vm5AӤȪ6sT⛰lL-SÁ`Ҿ~,b'٢ܯ%#NF]nOU+d#|n^ŦxgT+[!j ڕZ:z:AESno Ʊt&,BBlƦBL`)ˈ!f\@_H^2}ϗ'y-[b0`$ M\:^j> `7] u*cgϓΑ?ЇT|41@ _! #laRgFM~,WK# U}1*Z/|iFQ~|*;Qa発0O=~6jU :y"*~_\lvG,#T=H˓z BarW/Xt%CSpȅ襞 at衐d q}}& ֥aC l)@=YaG6""孜8/12^fnjQCB +]/QGktVO"i#q A*QEkDŃ)WxHaLN-H,&g(b: J˓. sXsmJC [AD,ӧ)h03 7bĸ|z&4+e /" W* +VRiV>JyjoC'N(8)-W%lAR8!f_x0܂ K|U䉹08DL-"G0uTzzDfT,JUY3|ddmJdԶ~~y!+z|〭?ur:ʩM.DϲIP2{φdeVC"oͮyA\1QU454gr,.E4yܵuh$e8n{c+nqҲW1 ~=H\Mu&^ϗc;~LhG-6h|9 k;5$ X3a >M- IڜvY9 )t& 2fcA<@p5g~0cKK $Fq;A潡Cu:f֎A.6MRݾ94%8ny48զ~VSEb+gԱAb³WhnXWe泆Zz@= ܰtJB؊ϴ A',ar¬W{R#:c%wFnj T֍vs U.@adCra3]ͩ4QLCvV0BC Mݩ>DkK 3A)SnAP Qi2v'Z?AҸxh/,ҨlSfVE(Q<^-y!At.t^eW_tu؊W)omr+ '"! X{i'JŞ3_|=tep&yJ랡?tY׌H +jT35'*1I[ +I.'E4vrL9N.;hl q⽂ `3SsXt" QZ5xs *5>'sEAo3Tc@I>=RPewAi;Bb[pN:˶|KR"Ug FY4)GSXTޡďl`"|NAܓWDJJѺNw(Ϝ0Ls\zP,֦rAttaD 5e}@Fk& @XxB:Am,b~7AfjRgc6è*;X)SڂQYҩSrxdk)¿P?aQsQ.ET13Q H:@ӽupT5CHXmHNډfϏ29s}2םFkD 04{{k#:Sdܣ4,5Q~bMF؅%CJMS5P3K[KznHi-m O&ES (ޝ1G*mIj닆h&HΜFQ B"U䏃m?55\qgAY %4f]ƹ#NtC1VZ]fkDuO?sw#wW9#kO q7%2< ʺcۑr9fvw> ffAe[eQ8ARb;HRinW߹o6C?Qj5+Əs'-,n$^tr[9oJ:*ʝ[KMx-!˙__ZeIkҭa 4_1v+|#t0Њ(@Zn/ʜb7S֝?I"׌ZBؾfEPV1~E$rF_+AoCg5nVOf,i<W;(`e` > nV0H6| 986q %~c+N# |wWk'_ߐ%J(!œ"ë9Yj==F]TCb0bY|Bty{At|%MCM^4I> bYҒe>m\JߨʺJA0QDr9б7#~EaW4kG|/_noogFԦX;}Á ,zG#Mj{>TbT ˯s30f?6U̬۝Cendstream endobj 158 0 obj 4228 endobj 169 0 obj <> stream xr5V\vLSc@RB$9ljWJQF~LE';ODLɛ$%t^x9{1 ԙnvN~|3{0saCv<_B &?NL5H-p+촃-CNuzu?rrx&v?x\@[xt.qԳ_\Rt}7Bd!%i\@?#<O 4C &:3AM#xK0/69iMp"ujBb+[,HeJ stp^$ -P#hҼ8O(?$ _Jdr>Oc ex\NJp΀GXMf^3³Wp֫pn: 栮=~?Yͬ/ knm w8QNDi35%fρZQ$A$DaSO Vp"O.kPn3G{h>JFgfqD뮬4mpfcsʆj Ol^6A$&{<{ ўpF85%@,+O|x}ݨ$Qހz7uޒIaʖJd.<'|G&d!U|O sGQDo*(ȅq/̀', r$m A)p% dl "Zr۠un^qY `$erv"`äݲxx˃ xƟZ>)oG%S!&㾓u/6EXA8! HyK洢v{2*L挧(0 k3S#^}N1ZNUIDߒ?-c"0 vzBIka!tAu7cFaOXtivE/k&͘Po'&V*jqpjerzjRZf(QCq VlF S}A^AMUp:z-E1RFj&'Y_h*ǰ)x',U[aW.$:ktb cpy#ژmL2a>X_V󬰒LnsC ̐5S_1(COoaD#b.EFHOof [ eٍ8f>8@-9GUyiEBcۦh#Khh%,RTEH%uǵu X8mDk1؂R KtWhl=PQ#*\2:L45sKhd,˨` .ɫZ"ƇP',LͲ SiCkGyj]D#'Af%Rv5wYFNĊ+oR*MBu*Ţ\a%Kn=S[V%pY؁ȍLN򁕱eعR9z XzCضqFWX75ңG.~i&Ehw@eW5J/e!Y+d怩Mq Ґ{3x bfr.l$؛\N40r]yQ ]&@]I¹ȩ筮PħY +V(.yܖb(rav4͵zBʋ1sV~4:N<ιK޳zAf= 6V\s_Q]zi59jrD;_k?QQo0w݉}n# >5ƶ s-/QժAj[Q q!JܠfQ;'n 5_e [x[#cS\Zm?,0\kBC*nxxeVNorbh0z{S]g?IiTK+b^vKdb N%:ܒRn\3gsǣe43Ys>n+UQcW qR/ȯH>Q ]Cn)WrHy=4L1+:Tw[9Z໥AvV$758u/V^mE}"([7]ʶ6N֌yَs #:]z!"suwHU_dOU3@S~QGК GT(q_sbendstream endobj 170 0 obj 3891 endobj 177 0 obj <> stream x\okCwn|."8i8j! WA _]I'KN%K8?N{/;:g3s8q&yw< /9 3xb|Ц|xhJ4nϳOvg_~+Yl;7B1𭕝Hdz28~vs19x׏G>y(\[`|謲j<.#l7,fYCLo;aE~4s΁]~Hkbb~'9\hJJi=_e3^qH|8yRx q>{6BIghn>Oc|D'Pf"SL-%0㣦Z j}qhv7 ZatWQG"eQ%03 ./d@>8t's!*+iL[yauuDi io)V7#݊ptO_.;i'ΞI,+yF^7 ʻߔeȶ4dT\J ${ħ季}E;]KnyuA]Ǥ\[ġ.XRedkʰIffr7Se?9=βaYzUe3;bզq[yA_7- gwH>*<g^3tWK(!]33L-zj?>vpl?qx`t^/EQ`RU᠕N.3A[SB8Ne_' @X& ݍ๥=Z!LOhUAUGiGx(lcqfuSbpTvn๺"CpܗXG@hJ͌XwL7Q^sDðDp긧"uImrx#u~XV.a]%,50cvY̬JYޑ=LAD0d9B|yZ:󠒘U{I y=UWfM B9ՈIۛpN:9~2aTsU x"yϱG 쓕*hXP"RPNi+p?ltSR $+DZieR\ ezel҂>h|`JUUnh2 `z=getA]^5h'Ge/1br|Ck1إ;Gʼn)PK_ u' &>_< .=RC*{--$+{@׶[PG0ӄÃ~W F:=_ٗkk\&. O76%^1a=\S00P"Qᨰɽ@y *T )v@ȊO l(F^ _ 0xsR^"%V˨9~6DGHfኂ3XL G,h4\=a?(K!@NԌ 1 h9/GM/&v&'UX _){?gI7QAN#+R^U ԉ4flDr+y'o'V+Z~5DUo {oOec#oT?z{j=vMw*tk̗ֈ9ә]оsIHE-C#ILQ)0Wm~ݛ gpx|qrd&Op9i<&osNG7iY:k;wu{K%@ ,$2jKS!ķv^c-LNfj=;eH"ʺoG ho{kݨ ʀ芕)]ܺ̈́&Yn[Ez(&D;{- Ը] ?lnA ̶ n]tԷTi\H+dil)UcTMórMkxXf/:> stream xkoյ+V;}ܠV!P7)*K?u loc?:wb}{ޯySyNgY3=04a:$!`vW3Z̭yM녨v!sv]w%otoUm[&Gj)gR4+̾0W0[QBJQ+ GZY }bO?7{?r^%X^BZ7;F_J..ֺi1-n Fi"5KqZNB7@#i!i;o/+ Atw{)AG-QEVTAs`8d'Hm%P"J:{',̀VH_&;utDi$'3MdQ0Y(m1d{WA bƽ4e(hR6@!07F@[ `ˆDHp]CL - I.! ӪF0ߧ6}dg+d?#MD|_I4*X{-[+IQzF!q?@_xR]Mledu 2? F+"kv=Ql| \a2h3& ko2J=]gpzzp NO? nh89ux#w$yyz%W,:}<汷&BW+s8|FZGg(YZ8=}LƄ v1dău7Gl|o4xQx%sm5\[cM,7E&}dnXbl5Fj2:] ,=G7cP])`D4[NZ’pA(ɺ2zHG3M*t}Q P0 w3i9gfAw"،G>%]UNQ{Ȋ{dqzc<]L^.j S=D/3f<}{̈́(o| ?〓_b.y:F u{|y60)Gz{Kq`ȮSx dv״Qyӟ'S_+ Rd_D{RXQKCvZ+#IoHi{%r_שqm:[W;"|CIlSOq[6{)-mgo{~/.Xv165l/I D/&&ߐNp+)h(|eeeײfR˚BYSuX,5S]j2[6۪|?SZEb߮甆5 ꜘMtfS! ଩w#p+hz^~}s*!l&\ǎ~N ?l]⊠&H0gF&0 = LM e>,#<kMĖa}[**x&f܁a9Q4~#;Z6m03es(Oqo%YLnksW՛H%؃ $ =QX%I;ch TyBc:JLXSlJ ?Ib.R_jlHIj1^„68k7@,*Mz8LCa3סjDC/iHơ& }@?cB*MZu" ƶ.dG|i9čq 6oaC]];G-/&ޏ!r؍V"~a)^#J,u0EcvLNSVş1O* 23R*`(#zچ8>d b'eV) hI(mjDj މЍb`]4pzU 'z7dȦÆ ސvhΊƆ . EP۱Ţj4n*̧dIOy'#&یBO09PݖV!"H9v TbL|OvhXjeAߕ#) <";\M;`[\ߞخE1g=x@aԂ2δ`2TN"IF1xK(^B "DpU :Ov<) \8 }*goJg $\#GLu=)>XQ&q0ňXwMJX՗&U-\7P( e GY-X Ud!vvΡpCY!̳HW֙2+ [uS:uiu(T}nYu^M܏zsɭG&lc */ɶ` {ܡ[;f0ǿ=(qӟ&66ZAh"{3R͍yZZY1u@1[PMfFP5Z {̨J_FqcT-XtM{܉vDCN5x&{kf5(5!/⠧ (s ?&Pd>4Wi0J||4l#Qzigՠ[E7hJI֘G[X[{,-j#sslʒibqs@;~t ľs?OFNѣon()3=ob Cyo($GxbgHȀza}_p1wō@,@S+7ÆTdE}j!ضGH W5To})uǺ*ä1Iԋ+!Q0bJNКaֽy $( J'jiUjܠmv醝א)&mGH0Iv #L '|usŻ70c9s{ 7תJxPJxE@N߻(ѫͻa݀5zU0?j´endstream endobj 187 0 obj 3933 endobj 194 0 obj <> stream x[Yo3?Oc[noVlȒM +%mb ?>UWpH;4c?NFL[/>I;''&Lï#,4}ۋ_-mM;mN.&Ꙭ.hG<;|*XZ7ӍjFYXke#,prpͧwM__fpr[m\IUm5m+{]Բg h[Wk.j PSL)'lou':\-~pJNb5ֵH)ܮ"yRH)0S4ZOg[7zG9H!4rTt5I&mlqcGD t:sVfȨh$\*d7˛|`=RKc3N/a)N4 " NL7h\$Mz3z37{g&ޥLWtQOmϪ$> ;ܶkR7B1L%)L!Уz~Wo.@w( l= ۛ)laSeǠ+pX18 P@ys/%/҅DoӵU6fm{=1Qb6¦k-GffVoF tKbp0uM V97i<w1爣P<~Up5f_ l'kKsv08Ehy$jA(doQyd8; {n, `\s'+,<ۨjUgK'c$?l%Yoq=OyP8Ϗɿ(^e`9_Lv4Og40ZVu`gc;7StRJYfMT'@7Z%)I,tjreY tn#@u)k{՛ڴkzLs6%~fj>s{T`S^HNJBsYAm{DԵz>֟KzEEFCf6Mz Y}\@@5#: we-K7[ekL}uE!ު6R+ "Ӎ\"$7<.͢]=.´R<[TZiCYjGȘ׊4D6U O 3]ǵ&yg5ONf3juE/mp+e1Y^lOK~}?Y'+뾙lL4Vdd)L|f2Nǚ_Wvΰק>O!7vqQfݾg{RҾgžg_N Ԡ}endstream endobj 195 0 obj 3097 endobj 206 0 obj <> stream xYYsF?BR5FzӾh0b<eC`Oe{ONAN?lS@"ba'+`%)]a@xJ#{xLp8]VAJ:xRnZ59` 3`i~@QRҳ%H |sfZ0%:׌H,*$.)O2eǠ7{ ~JxC%z~K<y9ZOs|]+2'rT(Cap\ A aP:Ӂ4ퟝÅYDx`PO:fo"7HOvϞZMV*As?’>OO)E2ԯ&x1d?q1>l^` QvdQxHm1ǝhCR1Ж­#>Sy47NE2of=]9Eh';]Ch3qg)v/A RQNj `JQq#)qpXj,61=P_O1K|ޢKΐ .Y!& eBd6AUx1iYǢ y,KgyU¶'3)po%SҹI!1Y'!vu[- .*l)"<ʅ"lg^u ߏNh X(1}j1J7O.NX@ZYSbbQrhg#֥8-#\b zIMR iԻDȨYС"hɚR'߼YKV[لA{KJ2ϼWd#؋m3 i PZ` ~AklqB.)bHWY38w92ʶ{4;" B͖[VX+A_GȥI`./ܐV:(~-d-1+67 JؙcZ $AYĽٹd[VI8Dц{/x]p!'ЛSOYbyw cJ5رj@K7G~/$钌UY$yl*ValޡAuJ/g5wJ3é.$j=Tn|KbKpHH-G]neļBC=+ڌ@mt 3֡4({Es|JaB@]R8sRk!t4(kXoO៥,Síi\A`%t*zB;;nS_hHDߑa|a_-~ ڽ?aH,PO;"n>:UKʕTi;iÄ5x+*2zEsȉNgnD[]M `W{wŊvݕʗ#^pvW'8 MF75IB,1S7#9\9,̺w] ktc4)^<˻{Q5`\jL}q09>ͫw TK])+E1X1IY7!?C+1|g+Ÿɨr4TdEޓxa+1UcayU> stream x\{ܶ/@E EJ$.;N h"86;w{P| ə^I |p/-r:wLlho:xg|,U AT^i_1+y=Y>e_m*(3[T{Om#>e!k?ᑃ1}3Ie{U5]cxs;: ;GwY.5?W;qzk't3>~0+hz06ޛuLAbb(M{Xb(uOOWrdB QHDSQ&{Ks^F.YwJ`.jQ^'ᄩcs{4pں-`{+AW91j%iJp0)Ej5*`9uH3KF6 8àB'bu8g@◭{9gc 9S(*1%`cLHH6 d$t]{USF~W3.8/wwxI/6CzX FbG/g 汐Kg u6\M.Tb=:N}^$$V'e8+7wg}9K<[zf ؾZo"tZ=Y.s"Xdc4'|C"6FPQ1tmn@hظ?D &FÒ'a5ǀ 3mpC2xP%r/QsjBk>'u )Wsz(s{/Ie,it%Z]n9U#Mq&TC,#K¯gƫEbUHe*L]\=^%WG몆"%eS)miss)ZD^ '<)VSAYf1_X6z4EtxĴfp{I U[׆u*j*Xm#.?]XɁ&K:75 - ֔+tRZ Z?2*}檏 ;@j<փ+-i{f<4ע~;Й9!iviua>%wy\">W(B!y &fTbyAX p5> )sKEGa`Rڦa佽ƫp:0Qrr' 9`\*H,9w9`*$^Hs+Cdd|m`9ȓvc>-%Jo52T. oaCaao\bR+ԗ\ yO6nh܆S.\77wq΀Fޗo^(I'sr݁gXJ.W)ij1(BejAja9-@IKO;kzÄ0$!w.S!7a<ͱ,|lϞmq}쿐zJϸ˫~-ߞ<sq$t!#6֟cLPd6i->;Is\j\rӫ60ƆѨEެN%xcQ:,/;[9\+FNRahIGI>lbIB\ pWxgP8FHb42Er}cv;er,Vgox_;02!im'KqCXqw(҉i+<}(Ly58 |:aQ2sò=&W#?B%UFGC /9k:gY$SDj8243]U-3YLuλv@Ep\:>B~?k-3m wmf/m՘=̿JE }iq_: &.j ,>ѷ#fIr|-7;{=yOQq m+gA '":Q9]H*O,9U \GfJ|ڱ7gap_]#q+UWzLت)'KgoZҞetya[@2̝U+|4ˉF Wx۵ci@"|!=k,C6yp+ͅܒ0JxCFВR/6u,~/@m0( J4pM$oX;^xϙOx9p^?dDG<o[5%l9}ݑ:W/k*q"؏nL{9.sq>K0FU=/ݍ|#ISQ ȩ]Z/ItjHHH 9 5:q3>_Gk"ye݅\,`$C~h3aw +?p/PFX wrzL]נf'& r|qьEs?e.ӮS Tq3-7IaI*:Hhveu:DDendstream endobj 214 0 obj 3636 endobj 217 0 obj <> stream xkoܸ/6z.MA7.?R83䌴ڵf({C}&q:Mߝ/lLb~&&i;`9>6uR};"eRO'\Gz6kUw&t"uYf]l^IeqFgE\UQEdz m"num/dJT&4P/q <|?yŒ;Ɲ7qzHPtGʱ呰0 ^βMhpw愀,99~-D"1™/5 gT]3x$/țྼFBѢ]̟%;x VX>Ϭ.-.PzQ1{F2a]B jBfMbi.cs`ȵiT5nFIpuO؞!JyehVfy\ @b+.&z`JOC7CɌC$$s81-[Z^U݃=3q|N٭%SKh1tbZ̉p^"֑|}ikp]M* mZ9$-܉u/u%u8)Y6A Uem4TV6LhU<1c3|ܤü,NX&ETY`*"a1K& zZ Un<5#8?Q? cLvy!y|жH/ఊ ֧*,*JuG"Z]u%\h-ƾ29 oZ^Ľ|l%DY𭴛'N8M2$:%K[j!+nQe`=ЭA`0ydyg{E`\h eK;=6j},lH=9ItSm'U P87"\2!ޒKp3DoaD7gܑsb+ a72YIx8Is#22#! Kx튯t}P(#PJ(otL*9䟠s8i=qA`|ӆ)x餮nhϰ|TJ3:T Gt,$3?y9NIgDFnORTPpڷH{~P;P9^l hّ;P]cMVl.LawCz qa(VdG6!Ø!s:5Tаeǁ:EؐgIx {ajZpJǩRH͓!uwH0%BNUMr&tO5(C<U~0.KLⳁ:P@>&Ĝ :P> J%7 X`<Ku>~dlM-+VUVefXatU@A?Q<Ô^HpaãT`._[9HwBK{*P_\q\X^r\l^+ΡLǤ[n/`| 2=MZNъy]+vVSґo+)J9+n|qI7T0憳P=7b!I} d2XQZ3n@ n};!!q퐻otJ|;Dm};Z> !D^2Rj( > stream xoݶq؏/z*9~(]?컙h'?{fRH䍘ͺ\:+y%UVd;],υSa -T%i5M]I?jtQ*󍨓g颰 !7im!4Ti"]:_*ƵY!{` v"҅XI.PBz(t&eB4_n'UYB'˴C-!ŹykP0*M CZUɱ2L-dr*YtFeAw/ͬB6*CGFbcO`+ul%X7U)93_l1B=ٚlXar|DhGf6Ni-P6y/dV׹:~vUy&QQ<1H;ޘ9샀˜H1:7&6Lea8bH#GM =) JV'>HTwb +)^sV!84fz1{DB#!)]D6bGQT)jsf4Ae3-N:ct>u:m+Tzu.eTVEgiBoT7wjN&DNk n$ۦhdYn.ֳei`b^[9: 2Untv/]H6yy-EVX޷o)m-Eҵ.nmhzB%ϩ"58..'60 kWAX뢐80ݬ7vbh ;w@릛G CoGFV>0ܹH0N-irU|J THAP=O`f"B }DŽbCmȰo..xDjA7 WWR /^z8aRTƃ|Z3deJ7>^F+:,#v<(OMUoFjC5Igbš/+)!;A"R)cPPHh ptft3og`54g(75;u,NAß5A2㲛lfUխdTz'V\?z_ʆ=Z8sdjQk"N(mwݙY(c1o!䰺dA eUJ3bEnZA2v?Ӑ+) 0ubYCڋQKO8hpP`O1pօy\,>:gF,W݀c6p<0/⚂3x^ph{A+rGEݓo2jbrL>GH1 B9hv2b8i⓿]^;Y3xl8dm=^" MAc~J3(Y +1$G sRRaGM;&W]|RE DcZ AP΅bD{t 2c}^']Ӄ(qܷa%K G94P$?Xp2;mn/f.* HOF*Hd/Y߅#$/V!ʫi蔷 &{D$Ua^MC A `3T,0^tSA`p(7Ō-\Ƅ%(,[ { lC,dvlPEe'VE>wqx{ z$X>z'>Mc TE$ Lrț`~(2>I> :B@ud2@S7XLNogKMف.) ѥn(:KxuN~hl lFqZCNO=5ǡ / 4ƼP&H2\~036Pp&H:j% CãK..kT![AZO?opck7tEdtNoKm"F['3GxfYiAEH8w_D.#.x:\Z<ءoOf5d@6r.XL`ŸÚ5%vBʡJ~rDLajhj*LpГܝ_ sċS}gK{'O!}nH0|\> stream x]Yq?bqp]w$JCv~Xha;3ʪ3UyY_Ou=OpW.N{"2-WWnua~_wjwfYajG̞`% m(zwOVE3%|3~iR>#pyJ|}cAA=A+,]KpuVkO2fN:=4+kF-K|-8M}_̳=z|Qj Zy}W_[g<-Zർ `' S}>߾y꓿\O~?>W\Ca9k SG{wf>~ +X۽2v [&ާ<,fX`{`&Z/=f LDpgpp+>OC4iec|c,;fxCh-MF/z}|@M-xrZ &܀z}^”ݦe/qSu?oUSOs Ӟ]W~Nog,\>G6',v(߇ :q/ p2Κ1=.w \)n1ʕI塿.Ӡ jV_Hz7(ļuflrqWvI}]gE=%Fa2SHI=Nfv]մ F[sDC`?aTN *6H&RϡBr_~E~  )vza40.aywٔ^eH=lmkYB/Zrzc$ *M<}H0iq"rFyv  骑Ғ(?%{ $ ^qUZ|xwq0YjKG ^^׉ $7=ɏe$e3v)C-4ǺyW|F`W43Bbo3 W}=#n !׭O-1Է2**vH]t=oyJ4#oaw%t?@7ajϐ]P=U( Jf-Z { Zϻ?lspߑا#؁%2B胙J͌mfuQ; &0bXiC欆'?򢳦w L!~:t}VHYdvJXKabܢ #Xlo_b E2,D(\vO{/voM\@-@ޞ*ǜ]*͏t|36OeO vBRk-|/.I|z}v(LqfPO€48_W+yگ4@F*ԃ"/RخP4.u_7of׽L>+"[3 ΢)[ׯ]ڎA4?\'eGtz~H4,h s!S"M]%ٸ9fuS,WHK[5B3pIƘ79Q!DM:֬o?Y9Ba62v6lM w&-H=S51Fw70LmuȨ]@:閙pi7, SY+#շcP4<=S t9.f 2.ʭw/#=μn=Pؠkf"&ɤ.г,|h/F 49mfQqTؙ EIG^O[̎xA5QpVH;fr ɦ3[ph!vLG>+2M# TWeCU,.B<=W, 0Uay|yHS`a%QB7XZOz|kd  &hطY>FJї3++Fe'&=X[mqt]6VŠǙ3m>2\ hM4 ~sI p@ՠٳҋGXNELw|T-mzlć K?ݣx|u^i8`]Ȼ8 v^ ޤШʒ}VM, -`x5 Y c({Y[>|Equ}~ƫ۵1WL LV^ эou󨞣^7zqT `\m!~dLVfp@ @+ơQh$N S:d/)nuMcl2QEM[< ހschl{5/?6 Q+3I{mƜSeAgi"3pG/'HP$җ`b6o(Ѹ1(>zfTq`:7}T_>~Y-/'j#"9EP %9)-Ϥ2#P2O)de^/^gM |5k3=z*wL@rf!^/!He>KXe=.;|h.|M/]yl;OPN];ք7ZIx'f&mpkH]xT9Oa(q_Mb q̿Ma(,se+j"(& D^*V1hi~g/Xc%ŎaP栰Y%lrIɣ#5DCWi,m ahEUXKL~&ő{DF$AC#1 ѱ̰tS#%,H%5 EsFH)廸P)gCHHjYMVMp[o}n>Dx)nZx' LN8y*aNeG{j}vwqr*z52S·J!բ1S,#MRDߝ)祢;\%qfb~Pc=e' T]=[ VG}F;#QBizJv1 )Ӑx ۬$f:KPg qJdEh~{}IW-ca, -@Jy_"ɶ#ݒhB:l(J@Dy;3O3? ~NO0rbࠂ{+ 0(lĜ-&يVv:- "AJ uz*egiT5/Y\ #}wYBؠ0tVP,Ђ.Cr,_ 5AZJ| crY}_vng S;K\@,~E0̓{BfGj"4Y` ZA,F fm#`=ј}v=;܆M=;̆EQdBLO%.i2@ xg2⽉%e{GXZ^yd=?%6G"0G䨖-GZ;tZ7:bnD)aZ/b靏G5<G4}zZPե+(yR)qE/Ji2KwDXrQtaρ;'-c,u"M,"'WIfq+4\Dznm6Yx55Z5 )Zd04 7r. q\vQs1u 59YaTg5NgCmG'Hh;mecq)3uR5KذW7r1ڑuu#,Y'Dy}yMh$0KkgeouB.nʹ!.F%):63XǻeoY^H)C}Jҙ3Tv]u L1d1xY-aV{b?G^(0d\]kL:F"tБ.BDW5Z j+l~4U((UKkSkpḸ"4fK(<£(29XVFrIFb:hSF^hfi ZWBkGB bnS݂F.]A%Tm,g7jYXE3>^Z1``);so@tV9g˔1jLr#s&f;rm^ ;FQKT-!klގQE ڄ˜&+pC g'Djr IUq) =3:QcƄc\K`Ѻj 7#L CfI.yUIFm3O'J <> + oQ2 5!%FM{\K2e岯bbka[|X}0rߊS-IdY7RV V1娐Otjwj..PyL<9CoQH nP=䶜`rK>F~ [4T^UBF]%=+@Au1m\1-P.gI dp}i1p%po@{.s^O+]30}d[VÑABX) Sj!Ru09h!-9kpjDCE2 1$%,1|TB"cm+אnew6'{ʛHRoikk9-y2bfѥ6Rrc'לLiRb:)c¬Pϙ=}V<9NKe Ȝ8 w-r7%0:[9;eKITF-[{VO ߡ 3镦@ ШO/˘}0Ž># הWal)xekpL2"z /1=^ }Q]D ҎZ.kl$ƳCRq)"/T)5Qo]LAޭ Z]J Q+hkB*-BUmjIưR rFuΒ񯸽4&,+݈Ugˤkx&Iiד]6֕6 oM4kġrg ~erY cqQ}d%#_Ic%nlgaħr(Ѐhj=V#WB9=heZ76Eɺ< 50~YOE\wƈ%9>tIiP}0$'7L1aS k;N;K*m Ѥm߽PIӽFgӉ7f.,ф3M5!BxzX]f~BIu U㤱Cܜ`]=TscʃJwÍbw('xk:҂dzxX6 \PߩÔ[C.ݡTzKrD>q:'O(ɖ8os9m̓uE _Q)9b'%58O ^rCǥ̽EgNr29Ɂe4#Ǽ9>BZ*Hf ^D2jϚ@7`nsK/ &8H FHtgjGdK !j󄝮.EcM,ǩlM#]>ѓ M`/&īզ jtQirdcɱ8FXl+$=2bMi_~\3_>zP=K8ZH?kԕN>d(6hĚT&5PAtfwzr_1n`˲}ww'^.?9ëP,xb̜SQpzO"IO2}Bc $b.XN[gKlrGӎ>!|))UzqA "vVXGb-g]1r1q="=R"RUv,7pi(W~((?G‡sr?pbuܣ$3Y  H>6Cw3̢9S!ЦX]%QwQx*n&V\R")jFK> C2:%_>t>~w&ϢYN?W׳&1R-!sK#: r!bN,: Ʋ̧a)Xi}#?O@aEU.'g:q@>R$j9Pq0߁!M:ª3YIAFmkUyt{4B񨫽.5+oF6 2C]ܒ^G`=^ BtSll3`qcEl{,LƽX9V` 4\-a'9z\rc"?r-:C}U_+*+$L>d%]8t1'wk7 ۄ`:GET矗]R3NU\)$s˞% w}WS]RḔȵRp4mUZd ƾ'gQ~>Ĥnrx4!bWN +4v,bO{cإ83DžrJME6{0н0us\!r?}-w% O#1kF=&9 ,qDLc|?4BX~;I7Nvw(dKfX؎2J.4X׊qlV1ǀNȴ-<(F}7cqzgAG1'\S8:c9i08wGc8DKolbzaA6c+J8@Sq-UG+AE:fX{G"QOڃsG|工zlwjdc6Hbߺld\*%ZIWѕcqAj-Ql9_4\nFiV[]V&RMNBHN_ X2j˚C1u?ׅot rZ;^/j.WVN"\}dUv$Vn9(H%X{$#Һ=:3$k*}?@endstream endobj 226 0 obj 9485 endobj 230 0 obj <> stream x][u~g#4Sh4;zmv8HUJAR*.ERXszNi;T3@/ ~Հſ_y/럟 W?d\ſ^s. nzݓpx5/=^3O8y<|SF`: Ͱ 6xRf>O ;ga0daj<\~8ڳ4V0h܏8y?/-EG7Aäf%j>;.']1\k>͓zG#(Sw)6N<`n̖ap["8,e˃_lr6e3n!)%ˣr3hGI!~q;63.Spa/q[~T`i n)#PaD v`"{tV&N*ZA {i{ , 2A m+r9 LG/i$JyN7t7J 01nk6yfm-5EO,R*OmqHzj4,6p/C 2-z,3˗!4Kr`n*p>ma0d>l8##Sd0Rtfٴ[j~m'T^qHm=,ZW9f@gݑTb2/$Fd22dZ5K,j5K#-=5DD Z{W(yI hU#;PȂ K֡ni,qN1՜lLh53'84Mf 37 lAMK1ZڋJ\`c-_$K&t:y-I*G v @(tm d8ѻE9`876r9oo]n g\ R,.WZ6)̺Ʊz7)<#|mY~b0wg3f55E N%=:b]/r777;*{8/[-pÝ D(XLeڀFtbL$`Iŵf&1uOv*,dй(K ;&qp#\XMFLviYmb趗ffdmq&̺ѵ0HǙفzX™heӀ'O֮|q2+=xYN(0aYpOupX`R#!yrz9aSc=V<c'Y|||ALjeT#+Ï@#CЗOW^ w< {>*a?lse4iV|S#"C6 LwRĉ$<<:)H#0a;^ku'h҄&:42Ѣ8 L,﫭F۴_t0@^`eC R 1#h2y~PGhM3D$3 gpdeAoQ :,Qr[+s RbXdgB R_1/lGb/t~ӲKUYY}FHVꖾM򮺰\#׊R,diBO$e"6@F[ϡ[d,ZPՂH\]F1. KF4` %qd6LOH \/2[37(a.uJBuapin#;2&$8yz("J_h ]J#8q9vPdNbG$ OuB$ ]7 t8 8m;EIY4O $Mr%.S %"l]RJY3f`%ǵa[y;at;!-M uqhnӰ0Kuc:g ݸY6F*F6k<"WĽ3s+2Fw},+cWqFtNa=/'(rZr1CqYcZ?6GDTcLQ!Q2F$']g]q ).g5UÃY!siwiijZfˤB$WxK)?,T!v~7IݏW539.wD§X# >k$#NGVC3z0(yh3eRVbl^R4WMÍ`I,3J|I3$h;-! Q2Shw$D7JLU#;q=b3u SɞnS=0:CJ"a[~!^xy.uSdX MF[j,NyYDXK'/# s2k .Y^A1iں +iQa~֙Nt/vvz8*+"X2ńtmr>|t 4y~SJHȬ!sʼnIPi%j]S֓e3+͋MwMߧ8,*ᾒaMl =+#B<6&X%Vh6s+8Ր~E0)~Téyh"S{AD삶#鶩MZF]n 2?Ck3ӞnLC"M魽{%2yGXB Ѽm4헍hAE)mGѨc_3X,K5DŽCmzT!Kȕ `YUO52J6ù} si-9|p[^ۋ*\$IIeؚY!g8q"x@ILG9T<[d{JKmq(HC6bD\G|ȤRKrF*Y %] 1Dci/Ҟ6(U :ɓACH E̖܆"#ˡ_XPM8H^dWzq3pb7(Eu(ƨu=# SBB(%Lm+d&ɺ:k(xNnX&\VғE tO(-/\_J&,_8;{"9S2iFW6MI"cT4a&ߦ[(% vQ2I~\# 嘕 E2b_,SThB&d߶\Y-Jm]`=<!Jrp' 6 W~O/*b+)'a7fk\U?b/U)NPa$җ7m#{ $'m25/ R&o]ެia7,֊{ͪ"urޟ;񨼌9V"iMSGMQ?+ 8'F r0[!* %yxޯtRWnhԗrY+I/CAGwHQ5c1 1msjfpQ%g3`Kll{yz6+e 4 jT屙 Ƅ>\a{M"c+7Jͧ]%0~>(v[EnI[&ܧRk pk\(Sgu{#_$~-fC ЖynmV$ڴH@jEM299Nalm.#̄Ygϟ7p[Dendstream endobj 231 0 obj 7198 endobj 234 0 obj <> stream xn5\O%7Z"dFq2B%* ߞz̰$RުRo׿HWޞxW/>]7goW7OM3%NJѬVӷ'ZadX+Gk%>J[^r=voP~~A sQW V|baji2c]ںlkRֽsOKշOO~>}%$WІڑ923JHyƽV??;=u{V9}oU 0D47 !;ɠ d#C]M7[?rlO/NGk=\}uY;? 3-C}pw?r S`_u|ΚPE~`sxg됟zfřgP7q5H-VeRE#M;H30x -96xL (aVu7VZهw@@+1T=PBl-"G$3@XݻN@2*) (]vH17RkdM"kcFkߍY1P.̪&J"wq Y:uLI;Jk-w'о", UBp:G:q.|Y>t 8j] -2Ԛ7 ɨ[Wb[)Nn"bTܭEwҴ"l(aέǎ;^Zp m)ȏÏIJ(Qa28w?>x=2S<TTcAWI"d3|m,wrG%;P%%լS-givǭQBl* VhЎS֞brKaUy5Q"4n^QBD* |6ʎwaSAӾvHFA+96ۅ -6`1AnфsbCM) k#o&(E :RPHG[YU7-z sB RH>3H9(>Nk~JR*y"XJL8>ֆ I{r l,j5 xV%&p(g[4UƋZT t%A %]2G2k Vޑ$+faqVS}3U*QN{(bJ'";g,QB(t0#Yh,/BXL78re1\WF IF.GHIH:,O7ň$rd1Yy!y]sNGl9bZ(f'XjZdOj}f)$;M㥦6Ni-ϱE \T,=b /j-]MWMkt-toR_F'PS?l9zv,q\*Sp-:c`]' i\֘1xP0ĺL7ݾ]UXT9)+wN9Aul|X1o,o=onS \'I-C cǎQubS Af.~l@b 0ƾ*gpk T mhL469MB ԩ@ ]W[ :4 6 5p&4஼r^H2eZYKEAYp5R[LT/g3*\Ia 3wX!Y+ȟ`^[P*;[IiƎy 58rFIJHrǑ䪂ĊW_b>\sUt+Þ ֧ĝ|U8"=6)=~.g/TNCqYP&B4 }xp{rd7n>\cpt@FmɅ1%KȌWt3$ bTڔ*|LjWś(y7sk񘑁, SW T~lsdY*&?Y Z\ ( RY1}"֮:E l5"1ɺ~Bh\ 5X) ]9&_B%BJތ"tVf&1' z 菏_Ρ(Ro{:cObCŋe1@7 Ă*:0(qmRLl`s;멳 1̴ bߔ~.`rld2}t;|h2 8iGf(R C_  sf&z ^w#3F~4g5*ZAyL(g' 9L Lw!ȋ lbmN6w?oiendstream endobj 235 0 obj 4404 endobj 332 0 obj <> stream xWn7~I K~yum%FQuHIJҸ@o.wWAUH!/5rf̜1%5SW7idF,F >.oRDf5m5s126i~3j-҉bթȯDkFA{LпοZnA(1J˜m עh椹cF$]1u2law,9VOW9wx̾a_5gItdgnd0RWҨÔ:Kgsb$:O_ <m&٥pp2L3pzrbX.!B.#**ʶջdD hz9nM$Spm/!"4i\MjR*W#]ڰe2}CH՟,xpT kS߶3ɨs*"3wϗ_`qOW"@8[jaXHl(,[դu5>JPvҡS7b$B t66fVSh*S 4 g[}hE䳢F# =c~} Hfm-U7ND-kZ[@)5  MAcPZɑ0'L|Sמ~VFCm:i4xOs^tt1L+e >?G>zi)ɵY2BAƵD%_i7$ fI5J*ּZpoesc MML4}zQ,)E\(/Gr~Voz?u(\uBk]&-w1H'S'㳁8),5 uVĀZ|{8 Qx;j BWf ٞ> /Annots[20 0 R 24 0 R 26 0 R 28 0 R 31 0 R 43 0 R 45 0 R 48 0 R 51 0 R 54 0 R 63 0 R 66 0 R]/Contents 5 0 R >> endobj 73 0 obj <> /Contents 74 0 R >> endobj 21 0 obj <> /Annots[91 0 R 92 0 R]/Contents 83 0 R >> endobj 95 0 obj <> /Annots[102 0 R 103 0 R]/Contents 96 0 R >> endobj 29 0 obj <> /Annots[108 0 R 109 0 R 110 0 R]/Contents 106 0 R >> endobj 34 0 obj <> /Annots[115 0 R 116 0 R]/Contents 113 0 R >> endobj 37 0 obj <> /Annots[121 0 R 122 0 R]/Contents 119 0 R >> endobj 41 0 obj <> /Annots[127 0 R 128 0 R 129 0 R 130 0 R 131 0 R 132 0 R 133 0 R 134 0 R]/Contents 125 0 R >> endobj 46 0 obj <> /Annots[141 0 R 142 0 R 143 0 R 144 0 R]/Contents 137 0 R >> endobj 49 0 obj <> /Annots[151 0 R 152 0 R 153 0 R]/Contents 149 0 R >> endobj 156 0 obj <> /Annots[159 0 R 160 0 R 161 0 R 162 0 R 163 0 R 164 0 R 165 0 R]/Contents 157 0 R >> endobj 168 0 obj <> /Annots[171 0 R 172 0 R 173 0 R]/Contents 169 0 R >> endobj 176 0 obj <> /Annots[179 0 R 180 0 R 181 0 R 182 0 R]/Contents 177 0 R >> endobj 185 0 obj <> /Annots[188 0 R 189 0 R 190 0 R]/Contents 186 0 R >> endobj 193 0 obj <> /Annots[196 0 R 197 0 R 198 0 R 199 0 R 200 0 R 201 0 R 202 0 R]/Contents 194 0 R >> endobj 205 0 obj <> /Annots[208 0 R 209 0 R 210 0 R]/Contents 206 0 R >> endobj 52 0 obj <> /Contents 213 0 R >> endobj 58 0 obj <> /Contents 217 0 R >> endobj 60 0 obj <> /Contents 221 0 R >> endobj 64 0 obj <> /Contents 225 0 R >> endobj 229 0 obj <> /Contents 230 0 R >> endobj 67 0 obj <> /Annots[236 0 R 237 0 R 238 0 R 239 0 R 240 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R 247 0 R 248 0 R 249 0 R 250 0 R 251 0 R 252 0 R 253 0 R 254 0 R 255 0 R 256 0 R 257 0 R 258 0 R 259 0 R 260 0 R 261 0 R 262 0 R 263 0 R 264 0 R 265 0 R 266 0 R 267 0 R 268 0 R 269 0 R 270 0 R 271 0 R 272 0 R 273 0 R 274 0 R 275 0 R 276 0 R 277 0 R 278 0 R 279 0 R 280 0 R 281 0 R 282 0 R 283 0 R 284 0 R 285 0 R 286 0 R 287 0 R 288 0 R 289 0 R 290 0 R 291 0 R 292 0 R 293 0 R 294 0 R 295 0 R 296 0 R 297 0 R 298 0 R 299 0 R 300 0 R 301 0 R 302 0 R 303 0 R 304 0 R 305 0 R 306 0 R 307 0 R 308 0 R 309 0 R 310 0 R 311 0 R 312 0 R 313 0 R 314 0 R 315 0 R 316 0 R 317 0 R 318 0 R 319 0 R 320 0 R 321 0 R 322 0 R 323 0 R 324 0 R 325 0 R 326 0 R 327 0 R 328 0 R]/Contents 234 0 R >> endobj 331 0 obj <> /Annots[334 0 R 335 0 R 336 0 R 337 0 R 338 0 R 339 0 R 340 0 R 341 0 R 342 0 R 343 0 R 344 0 R 345 0 R]/Contents 332 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 73 0 R 21 0 R 95 0 R 29 0 R 34 0 R 37 0 R 41 0 R 46 0 R 49 0 R 156 0 R 168 0 R 176 0 R 185 0 R 193 0 R 205 0 R 52 0 R 58 0 R 60 0 R 64 0 R 229 0 R 67 0 R 331 0 R ] /Count 23 >> endobj 22 0 obj << /Count 5 /First 23 0 R /Last 68 0 R >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 20 0 obj <>endobj 24 0 obj <>endobj 26 0 obj <>endobj 25 0 obj << /Title(Limitations) /Dest [21 0 R /XYZ null null null] /Parent 23 0 R /Next 27 0 R >> endobj 27 0 obj << /Title(INI file syntax) /Dest [21 0 R /XYZ null null null] /Parent 23 0 R /Prev 25 0 R >> endobj 28 0 obj <>endobj 23 0 obj << /Title(Introduction) /Dest [21 0 R /XYZ null null null] /Count -2 /Parent 22 0 R /Next 30 0 R /First 25 0 R /Last 27 0 R >> endobj 31 0 obj <>endobj 33 0 obj << /Title(I/O functions) /Dest [29 0 R /XYZ null null null] /Parent 32 0 R /Next 35 0 R >> endobj 35 0 obj << /Title(Buffer size \(maximum line length\)) /Dest [34 0 R /XYZ null null null] /Parent 32 0 R /Prev 33 0 R /Next 36 0 R >> endobj 36 0 obj << /Title(Read-only support) /Dest [34 0 R /XYZ null null null] /Parent 32 0 R /Prev 35 0 R /Next 38 0 R >> endobj 38 0 obj << /Title(Rational number support) /Dest [37 0 R /XYZ null null null] /Parent 32 0 R /Prev 36 0 R /Next 39 0 R >> endobj 39 0 obj << /Title(Unicode \(enable/disable\)) /Dest [37 0 R /XYZ null null null] /Parent 32 0 R /Prev 38 0 R /Next 40 0 R >> endobj 40 0 obj << /Title(Line termination) /Dest [37 0 R /XYZ null null null] /Parent 32 0 R /Prev 39 0 R /Next 42 0 R >> endobj 42 0 obj << /Title(Summary of configuration macros) /Dest [41 0 R /XYZ null null null] /Parent 32 0 R /Prev 40 0 R >> endobj 43 0 obj <>endobj 32 0 obj << /Title(The "glue" file) /Dest [29 0 R /XYZ null null null] /Count -7 /Parent 30 0 R /Next 44 0 R /First 33 0 R /Last 42 0 R >> endobj 45 0 obj <>endobj 44 0 obj << /Title(Multi-tasking) /Dest [41 0 R /XYZ null null null] /Parent 30 0 R /Prev 32 0 R /Next 47 0 R >> endobj 47 0 obj << /Title(Key and section enumeration) /Dest [46 0 R /XYZ null null null] /Parent 30 0 R /Prev 44 0 R >> endobj 48 0 obj <>endobj 30 0 obj << /Title(Using minIni) /Dest [29 0 R /XYZ null null null] /Count -3 /Parent 22 0 R /Prev 23 0 R /Next 50 0 R /First 32 0 R /Last 47 0 R >> endobj 51 0 obj <>endobj 50 0 obj << /Title(Function reference) /Dest [49 0 R /XYZ null null null] /Parent 22 0 R /Prev 30 0 R /Next 53 0 R >> endobj 54 0 obj <>endobj 56 0 obj << /Title(stdio \(standard C/C++ library\)) /Dest [52 0 R /XYZ null null null] /Parent 55 0 R /Next 57 0 R >> endobj 57 0 obj << /Title(CCS FAT library \(http://www.ccsinfo.com\)) /Dest [52 0 R /XYZ null null null] /Parent 55 0 R /Prev 56 0 R /Next 59 0 R >> endobj 59 0 obj << /Title(EFSL \(http://www.efsl.be/\)) /Dest [58 0 R /XYZ null null null] /Parent 55 0 R /Prev 57 0 R /Next 61 0 R >> endobj 61 0 obj << /Title(FatFs & Tiny-FatFs \(http://elm-chan.org/\)) /Dest [60 0 R /XYZ null null null] /Parent 55 0 R /Prev 59 0 R /Next 62 0 R >> endobj 62 0 obj << /Title("Memory Disk Drive" file system \(Microchip\)) /Dest [60 0 R /XYZ null null null] /Parent 55 0 R /Prev 61 0 R >> endobj 63 0 obj <>endobj 55 0 obj << /Title(Example glue files) /Dest [52 0 R /XYZ null null null] /Count -5 /Parent 53 0 R /Next 65 0 R /First 56 0 R /Last 62 0 R >> endobj 65 0 obj << /Title(License) /Dest [64 0 R /XYZ null null null] /Parent 53 0 R /Prev 55 0 R >> endobj 66 0 obj <>endobj 53 0 obj << /Title(Appendices) /Dest [52 0 R /XYZ null null null] /Count -2 /Parent 22 0 R /Prev 50 0 R /Next 68 0 R /First 55 0 R /Last 65 0 R >> endobj 71 0 obj <> endobj 72 0 obj <> endobj 81 0 obj <> endobj 82 0 obj <> endobj 91 0 obj <>endobj 92 0 obj <>endobj 93 0 obj <> endobj 94 0 obj <> endobj 102 0 obj <>endobj 103 0 obj <>endobj 104 0 obj <> endobj 105 0 obj <> endobj 108 0 obj <>endobj 109 0 obj <>endobj 110 0 obj <>endobj 111 0 obj <> endobj 112 0 obj <> endobj 115 0 obj <>endobj 116 0 obj <>endobj 117 0 obj <> endobj 118 0 obj <> endobj 121 0 obj <>endobj 122 0 obj <>endobj 123 0 obj <> endobj 124 0 obj <> endobj 127 0 obj <>endobj 128 0 obj <>endobj 129 0 obj <>endobj 130 0 obj <>endobj 131 0 obj <>endobj 132 0 obj <>endobj 133 0 obj <>endobj 134 0 obj <>endobj 135 0 obj <> endobj 136 0 obj <> endobj 141 0 obj <>endobj 142 0 obj <>endobj 143 0 obj <>endobj 144 0 obj <>endobj 147 0 obj <> endobj 148 0 obj <> endobj 151 0 obj <>endobj 152 0 obj <>endobj 153 0 obj <>endobj 154 0 obj <> endobj 155 0 obj <> endobj 159 0 obj <>endobj 160 0 obj <>endobj 161 0 obj <>endobj 162 0 obj <>endobj 163 0 obj <>endobj 164 0 obj <>endobj 165 0 obj <>endobj 166 0 obj <> endobj 167 0 obj <> endobj 171 0 obj <>endobj 172 0 obj <>endobj 173 0 obj <>endobj 174 0 obj <> endobj 175 0 obj <> endobj 179 0 obj <>endobj 180 0 obj <>endobj 181 0 obj <>endobj 182 0 obj <>endobj 183 0 obj <> endobj 184 0 obj <> endobj 188 0 obj <>endobj 189 0 obj <>endobj 190 0 obj <>endobj 191 0 obj <> endobj 192 0 obj <> endobj 196 0 obj <>endobj 197 0 obj <>endobj 198 0 obj <>endobj 199 0 obj <>endobj 200 0 obj <>endobj 201 0 obj <>endobj 202 0 obj <>endobj 203 0 obj <> endobj 204 0 obj <> endobj 208 0 obj <>endobj 209 0 obj <>endobj 210 0 obj <>endobj 211 0 obj <> endobj 212 0 obj <> endobj 215 0 obj <> endobj 216 0 obj <> endobj 219 0 obj <> endobj 220 0 obj <> endobj 223 0 obj <> endobj 224 0 obj <> endobj 227 0 obj <> endobj 228 0 obj <> endobj 232 0 obj <> endobj 233 0 obj <> endobj 236 0 obj <>endobj 237 0 obj <>endobj 238 0 obj <>endobj 239 0 obj <>endobj 240 0 obj <>endobj 241 0 obj <>endobj 242 0 obj <>endobj 243 0 obj <>endobj 244 0 obj <>endobj 245 0 obj <>endobj 246 0 obj <>endobj 247 0 obj <>endobj 248 0 obj <>endobj 249 0 obj <>endobj 250 0 obj <>endobj 251 0 obj <>endobj 252 0 obj <>endobj 253 0 obj <>endobj 254 0 obj <>endobj 255 0 obj <>endobj 256 0 obj <>endobj 257 0 obj <>endobj 258 0 obj <>endobj 259 0 obj <>endobj 260 0 obj <>endobj 261 0 obj <>endobj 262 0 obj <>endobj 263 0 obj <>endobj 264 0 obj <>endobj 265 0 obj <>endobj 266 0 obj <>endobj 267 0 obj <>endobj 268 0 obj <>endobj 269 0 obj <>endobj 270 0 obj <>endobj 271 0 obj <>endobj 272 0 obj <>endobj 273 0 obj <>endobj 274 0 obj <>endobj 275 0 obj <>endobj 276 0 obj <>endobj 277 0 obj <>endobj 278 0 obj <>endobj 279 0 obj <>endobj 280 0 obj <>endobj 281 0 obj <>endobj 282 0 obj <>endobj 283 0 obj <>endobj 284 0 obj <>endobj 285 0 obj <>endobj 286 0 obj <>endobj 287 0 obj <>endobj 288 0 obj <>endobj 289 0 obj <>endobj 290 0 obj <>endobj 291 0 obj <>endobj 292 0 obj <>endobj 293 0 obj <>endobj 294 0 obj <>endobj 295 0 obj <>endobj 296 0 obj <>endobj 297 0 obj <>endobj 298 0 obj <>endobj 299 0 obj <>endobj 300 0 obj <>endobj 301 0 obj <>endobj 302 0 obj <>endobj 303 0 obj <>endobj 304 0 obj <>endobj 305 0 obj <>endobj 306 0 obj <>endobj 307 0 obj <>endobj 308 0 obj <>endobj 309 0 obj <>endobj 310 0 obj <>endobj 311 0 obj <>endobj 312 0 obj <>endobj 313 0 obj <>endobj 314 0 obj <>endobj 315 0 obj <>endobj 316 0 obj <>endobj 317 0 obj <>endobj 318 0 obj <>endobj 319 0 obj <>endobj 320 0 obj <>endobj 321 0 obj <>endobj 322 0 obj <>endobj 323 0 obj <>endobj 324 0 obj <>endobj 325 0 obj <>endobj 326 0 obj <>endobj 327 0 obj <>endobj 328 0 obj <>endobj 329 0 obj <> endobj 330 0 obj <> endobj 334 0 obj <>endobj 335 0 obj <>endobj 336 0 obj <>endobj 337 0 obj <>endobj 338 0 obj <>endobj 339 0 obj <>endobj 340 0 obj <>endobj 341 0 obj <>endobj 342 0 obj <>endobj 343 0 obj <>endobj 344 0 obj <>endobj 345 0 obj <>endobj 346 0 obj <> endobj 347 0 obj <> endobj 19 0 obj <> endobj 364 0 obj <> endobj 17 0 obj <> endobj 365 0 obj <> endobj 15 0 obj <> endobj 366 0 obj <> endobj 146 0 obj <> endobj 367 0 obj <> endobj 13 0 obj <> endobj 140 0 obj <> endobj 368 0 obj <> endobj 11 0 obj <> endobj 369 0 obj <> endobj 9 0 obj <> endobj 370 0 obj <> endobj 101 0 obj <> endobj 371 0 obj <> endobj 99 0 obj <> endobj 372 0 obj <> endobj 90 0 obj <> endobj 88 0 obj <> endobj 86 0 obj <> endobj 373 0 obj <> endobj 374 0 obj <>stream x]10 E7hkVe)  .:NNI)÷d #zr&^šaɋjD 7_ȰةnwPDCLսsZؿγBZEX6rnfZSbɕR/{$XRI}QC endstream endobj 80 0 obj <> endobj 375 0 obj <> endobj 78 0 obj <> endobj 70 0 obj <> endobj 18 0 obj <> endobj 348 0 obj <>stream xcd`ab`dddw441H3a!=+k7s7BcG``fd/mq/,L(QHT04Q020TpM-LNSM,HM,rr3SK*4l2JJ s4u3K2RSRSJsS NӃP%E )Ey V L,J?:++-.^br| 8O6{B߉Wq]b1ùd"XZ endstream endobj 16 0 obj <> endobj 349 0 obj <>stream xXy\SWLZHR,hk.jUT ".(KHH-@BNa {AEYֶ.vfu:ck[x_wpi>?»{~9܈ɓ777-RiDDyB˴=};0=?KRA;xL4q3zz;92w<1-I-\d(2M41"Z#VHbeYGX*OL˔D[b2N,HŢ՛։f IRQprT% De QO,(J8Z-݆G6/ųedng9ٲԴbA@rWR|uVVFPqUV_> CVGT@NF~Rn ߵ=Z[{:`ȩ`lz$bNӐvb#Z/. Tt|; ~^8rISS'@nL}EQ&Pſ[ H3WrTlܪZ\c=B{8ն4Qvef~9m6ۋ+Ԑ%buQ.ǓiKRm^7#uoqtPk/;II8'@!$Ͷ䘔Hnڰ#%4k{@K1d5pZt`+h/cN&Hȁ '>':BFܚo39 J{"al=IvoZx|;=7Imŷ#2&5^ >uԤ)ʖ颪 }5БscKtܱ9 qM!ӻ øW F9AQz}KB,-'dC`рo񹁅Yk't>f:&s^zT[-G֘r걙aCqJ)߽S8~Bn}}J-*WAN:^y Ա'#[5]#Gh*#-ɥ C aYa.w;y N#]gn^ESD&*DiŠC\ܣAlЛ;wmթaߠc'E c׿&Lk}bjNp*/(ɱdo,OGX)ǔnw]-FaLCP DlV~cTpu;6T\Xl"x+e}4^i0>F^cf|RsLW;IoW, ^+`"8zhd[ZGBsI4qNLlnf$w$•%'*e޾a|s6`&3y[ EEc+RGQXZF|SY6} !;g8h2.*tPAOpڧRD.ٽ] !-#/J?^5մY %(Z8 1\8tB&~IFG owq~9m)Ini\jptT_AΏ/_C?".1h m/w6lvC1Mǰ:r{DOfc75 /TG֫kjҎjX /3YF@ȦU"эq_^#bΦTqIpDRV2ybzL@z=h*ieX_O4 sgt< 7w1:ͭ. L܅AR2BKlca&O3\Ъ1ZpT2>Y\Pg~iK }tM1yӜFĺ_h}`COb$hW+pe.(SITٙW'$6\Mڜ7F\L']UkEy<&"@9Fu4Wءn, AMYzn/$~ji!t{Kkj=zfFNCp <{dD[]V|oy i H\Pvv.dtu]w͛]E{ʙE1m;AvdE*vBq5oY?7PӠ&x֢|.#}n_z=-kx/(o˚%F`hKpZ=}G`lk^twip ABև|Y9X+7l !^Ձ#*]G]T~4}fѽὂQM8dND=% ?R{7;z?ETUo>48o}}MxiKm0˽|dnN5H|[ gͶ%)–ьK) 愄U~>꼧9&{l4|D7Ѝ^72b;Y~fEOW^85uRS͙yf~Nt*aAv**W *2l$?&uڢ:@,9OeTt^EsYgH}pn=LVgiKpblENlVa8 : G cV^;N Ub;v.SƼbfu-(HxQV4-#]Z-׊5  `%T ,E97e`;/G(h24_}Hx`eui/Gh*=>N,< !Dϒ XH8Je *i.; 8V ]$Zeܽn yGM(~Onk&JX%lgךp@@kkKs=.Z>}ԭ::wݝJ7`e9#ܲ _Cxƶ& ߩ>iV6˰0s}yYl] `OqrA338O!UYae&W2U:3<ܛۙ^IJ=;;(ǥቷ,R)gEC2jۡX["IO8yuhi!d nnb.71G'pŒ`:87"ÛGItJ[O0q&x怮l;u 2~;ˇӫAklm 2}ع[pt-h hguevO}ٽ{E 2h-o⪯ Oj\`7Fx_p/\#a[Y d8vXm# X/7- {Ng:67-`1y`H2[7=닾#w;mD!.  ȝ3.w;MDdpIk&VѨW ? F:`ŲM~',z 'h#fE2}Q9Jx9^7d1 8C-g'm p}]>~2|T,O(NT\^[w[a9P m$3 V'9}ۣ+ <پ<2D0̮ G/7*QmN3& :NP#z52*d6%0ڠ5h)0dSF,F>YLG& ,X[ANߦ3ueVtբ&kNpTj#]7 ]YI$@3|,V-mϵyqExhzTfA} ʬ^89VIIh,Y̻&_*Az Lo(W5WeYܜ,s9]Ips, ~F&QٺlsNg0S\eruE<*NΞݱ—Y?V -ëzS%MΩO$8:#wź - :-#K@yHR THYm*/;SC.h.%pݚB]4jXyH>1u )驪2a._C42Rڢw}'c4{G5Xzjܺp!A| רnMT ux^B#b'76RXmcox SnNV\ktL ű{'yxb ّYT\>25'_DGF$^;Qd=^z4zM{g?ڊMcYXS86zן6{x\xL!- endstream endobj 14 0 obj <> endobj 350 0 obj <>stream xy TWw ]1VMqkb\DMcܢ(/;j5ݷwZDQqhL4u&InG^1g2Vw߽{d2y˜I)/_/?u$Bo9ix՞iey0?c':9M{q҄ Ns<܂EzE_W<"Gy7jx0Ǽut P-Qmc*($2+q+,a%KD{,\|^CW,YnߪEX$*}ͫFߘ1a⤍̞:ӦowzyƬgg3fyyd2Wg]f"3Y,bF1hƅYLa0f*3Y,ed1ke\5fLg dz1;ӗyg0~@g2/1jf3 b16t[p{K !!%)UCDcO`.C P,XX< ILiD%#7,|@䌖U%aѡ[}O|u䛺]G/-2cu'[9:n^ dTIVz%cj`1= .=pQudvZ_\z@vb/rAGk5AͅT[jʊ!JP K?A8{CjA"D.s \‰p҃kUENMh'kapdO#IllAmgn6}lاqQш 鉅 ,7l;0aIIay8>Q) ܫBU! jyޮc/) NZD~;SC|~webYv(|£ejpK/KX%I];яm9&=$CZd{Irqgf̐%v2öATS9P"6tShHmI?>4#]>/я~!H_1Ч#+=Y{K}pZӰ_Uh4 AI8 UETZнUL9מbӃn([M-r 6HQ8֑%e,ϱG#vf>tZŰ uJI7puo+lω3a'dT80;xݻ lQvΤT[;V٥EUCv\j $hw/<47C$O&.@ڣ]!k Z2t4pdǘG=2ZiJȆLJ T")jqH ^ǖrE&ݬ3MOiuMkpyodmʳ,+ץ7eb%_wTx0=ɞW3tOiʽw\\Q|Y&"| 4j8CUt!G)Owhtމ,ɻprj>ޫhiDi ~wwgyG+q#Nd+q#ӈH4&gkNr> U7I,1kd}q?AKu+ЙÉdnK_WpЊ}.E \n AVgᡙBˈY\)|^w>Olǐ7ZZd.1hH Z.x-p {^v1UJ;r(֮AW~VhbKv^#ia;-)Q55;wִl[=sas\͈t4m}ρ,MM=#Yx |?"6ߐQξϊ3*$a`;?|Y"]`F+P2 d*Tt{Vj5;4P(YF|R )SL )ĸepCK qAcۉ+;R YBR6Ϳ:~geyQ]C@u  ?+?΁V ?Zu/o{i^&Y#Ok{wW+5CjjJ*Z]P\PSQeum(ln셳ӐRag9iW`@#>Mg츤hxЂAbEWv4~ 7)j(jÇ88^W p_߬˄XCƠLYΠ=p?(x77 Vv)HB 3Y(;|ȫfP*VY#vBWM }O']anzpw`MT _tV[4dX@Gb2Pg/oLỵٓUx#Yoӂ؆K=~9An!M`gzZqz c7IL;J&R?aq:NTvO}x]hsa \K;f/ Y#׆[B}j#-Uys;(?f*nREpZ7?$N'܅S XcJS.'hdg{L7O8rUVsw22ե-X9X2 % "[veNɜ!dg[}5cIyӽ_Pvw'h h. ;#i_X_oXbZgz{%.FQj.ugًswߙrL[,/eMRB3ʿۇ4}o,-д?zH4b'ߨPZ"j+,D.gK륝H9Xu\4$8Jr9zqA)L{n VI{iPނ?%PE {<+N'LJ2q m-GaP}z4q4TU`ܑ<@SݟA' IŰҲs%&U*r+yӾ梉nnѽH>] ZDFbPl1N'QFBhoOvHsphь~+V)U>#:w !߱D:k w.4g8C}(CGNbUvmAp ?esk^S\R \}DE@`{Ε{ĭb\ J֔VV RSX;`sQ~Pm xw|9vC01p(KLj}. 2ʫGk 4iwS_'I#1wGiZe |7L< [r F%>#֬-'1g-G9fĦ%kfFE]hܽc1o {34Q44=iR`0K*6 rx6qoP,()-)֖d)U g)tsC&VSzcg7Z-kgzJh`7 3㦅l^H᫸(:q [pΑ q\^~0*-/H ONMLIQ$jvbNeq+ٙN ƉpAWЭs\ u;mi#o17hX>ntuEOaT3'B!66fL\C:BaAF>łq:FCI7I=Cur.fC]wXLL(Eŗsm:Jϒm\1wմ}Tt:=3] ԟ'pݬZCIPR*KL:elӺmoOȠW(6C'PT Avy}R0se6겎V/fo ъ 7jrN 5 O'Nd &0:X>jd r>b}n|6;+Lt'sŘ|~e|o >#&}GD9$Y3+=ެ$Q i]$۫,IL"njeOy<Θ>kI^͛A 's9μQvb(u|f8.KKMz.`~Saeӂ}g4G)%Wj4w}EӁ!6WS!hct"_s$n <;s;22]>Ï /oɦ":S/T2;xL#@^2t?QzeA^Δ$؛pŀO4ҹ>^{tHH12wf~Gⵘj)fLL@K1'_~E'P7TQ( H2^-EiE~%TVE@3| 8!gp%^Y'O=zjK*6k~j7G߹/87GU`Oe*O=S.+֏Q*Fi`.eU8[.j:R;jBHLJB|czJ1ڜ M6{a oj; zH>՛bCBT%AŹ4Ȏr1?΋Re3hs z< +I,9o5[q\/¶ 8_8T=HivfAM9~їU’ U%\6 י)QĈ}{``]yy$+->Uv'>&\)t펷!T3O_9|qe26卵-)9֒5®>-ޚla I HRZtieuRfIzFrvrķI4Dy"߾*EUqC->i}U?˱ʭk']Iy+=&vSrwCW^RŸr|=ڒkG+p>4.3ʣvR|MBか{;x.r[ܦ@JNSĸl(rZI#y+-ȄTvV[lu:U ![Rp%;{bf0S28P)Ԁqu,;JWI%x+\./ʑX/KlVJQ<M\V2L%kRC`$ce+Lii%B. dw-Qhқ+8p gėp9G$T4+gFB77kmdǣ\u=-8 _bcuP$5&Su$W4Ut=]Jrv EFS^v6@͆tmgEЖ0a1,]h;+^\&ޚq ڴc#eM OynT7GǢQt ]yˍZىGX ne^n:pĞ Ӗ@0VYWWRZ{h2"$,v?=A8`_I[\7G 2_i+7*nEu6{QuxE.EQxdņmՂV.*dW޶U㇓ 'cǭ^ ,%)o +Ll*c>GvH>5iL]1% Sa΅PHqp[l "dX%¦p0_hf]i9 9 +h+\<>8﵍~%jd[fiU]`G.C&2vqI7zcZ0o!̬=J0{Ʃo<}rۇЁYH[:|P_~"~%x'FHWӮa_hu=]h$= SV9 ~0#=o|pB C:Ceָ/G^f]ʒ6Z;~oNiJ^BŽZ۫->uE'E*[:'<؇|w 1Tǥǔj GlX;u8sK-fZi޽~a/j endstream endobj 145 0 obj <> endobj 351 0 obj <>stream xmPSWoLXI,uˊZwX]wZ[|邮J$ !4$$$@^H% Qkuۮ:-uܩZ_3v~g?s8op*f9 WZ|ɪLEr!72_j .b,k$ њ%%Ņ ֕ޔkDe5 XZ`7ݲbF BzQZ^[#mY+m*(.qX׊JeM QyT,/nY&mV*rQV,o""I&)ۢݘK;D)Ml%vb#QFHEli_‚bޏx]YTc~bƞ)0&:av}EC=p6AW!˕Q/&LB]{aYB0ao3mmB$ 7|#ag1wwvg\.gGOGyOҰ ^r^x|4Yk} XO?DG/N"\%UQyP,w^ 2wPL-_+p>hw(MȶKs:}4?Vmoɡ-tݵU@1 t$ֳw4E)Вyo~}j-t[[]vFқ<*BdWɤoZ:/3)4| }dr? G%4~@Bd,:8lz/}0YAa3L _bv6K!qE̤FD|$}WTA'.D3C'ci1Ne4i@KbdJǶ]Ꞡ'{('}l |(N09r)f.1MmSwR-g$Z<?L v{8̪#%+Ah鉇A}H)gkiE+gF`nZ.ՊsNGC"3mg=W"8Wpȼ.py]p.ӛv*/u8:-N:߿V>Ou(lrF龦y/ nǗ@9=))'.7GAlk}P?Y?FCu {7,&TCZJك`uTxe{f^-Z6 lZBo r[\4ЂGh`(]OМ¨>77fkقO/#V5kqQXtN:lz8>ry o>8pvl2X[H-S~x« ,j4duJ| ÁR#SSt_rF Adk x!F927*jg:Yqd(4T~fF3u`ǁ[ABLLbޯ츯ϷbG6j Κn VYh8. YgڇvB\uZTޏAVlʹDh{kS6[N0@ɩ$5. PC zÞy_uc"=AY_g~*py|Ąiipd Ndq /~mWe顤0^clZn)D)ass{e_ퟙ[: r9p*F'BS^!{;PKtV:ij@> E5c0ǵe_ OUԶ|r1ߊ-Ƶ켄VP.|* yȓ-Mʖ˪&^*|z.yAfs/jqEPTΝ^`nvŸ˾  endstream endobj 12 0 obj <> endobj 352 0 obj <>stream x}ViTTWEW ܋r 8ǙFe,yJA,)Kp 4 AMڼ}>^}"z[Vݪgso{( >pC`P,/)]W2X: L; ™>NEMU`>&"5z]~58&AmdGJ+,p*~NwqH,䐰`nFM$l]!y og@ZQN y|8LH5kJ#DkMŵM-}UaMXz +eOL`$9H_b7_$R?;rNncuMZ-p.W0g,%uҤ0JmJ9[. wsMMfE)> nI[#p]s0m|Y!(x%;MIGɒd/wphypQ€^^eZ'ڼe t27.t3}c0ɊI]ۄqQ*XQa>l: u{X $7Y\+}r>f&")*2|hl&kmw z{Hw!2Neg_O,f6F 45[-6^B ذ1_)W-GcC%;Jw: [I9b+/qm%ׅ @1˒p)5$SrcH&:TNvFkpu٬ُqM96 ֳyQq.JXLe[L6'Z0TH{v$v_s0v8K3Lh ! M Ъt _R/R}JgD^׮^tzҩ8ˡWs+t'R͇N&»|HD=bhKqP |.eH%. +J Ql8ZRڔtY}}rfD;}gZRec% N]8:P"@Sso'XEl9d-DZ:Tm=ÅuJUmN樓-[|Ý3A72L2\k?u7sf紵1$Hð~nRWnVjp TNКѭꪆ@(tK{)b~.R DS#*3/Bz:շx37XmJM7$r7D/y*vsT9 6p409DUEIQ dkhUP\Jy5>8aR+e5sNzpU o͒>OD[Y!7h)]\R[ZWsQSo2z`m9ѐ]}x?ͭɫͧD2X#:؏N~?($ ^3e[ӛk]#6^Z|Xҭ?A- P+^d2z[;{6h[-rޝ℧ 8ty8=τ (*3+ŎVzaoLI<׸^aS|h|XX^j\Ro&=͙3LgSzy }YY:s x/ե"Rpm]ufχ,ixclJ|>oOgt:wY}%nx.==|.qe!Į(+t7NȲRom?4du&EwΛÛu^)VR+kw-γxzxzx2̿# endstream endobj 139 0 obj <> endobj 353 0 obj <>stream xcd`ab`ddds 4T~H3a!G*k7s7bBO``ad+ns/,L(QHT04Q020TpM-LNSM,HM,rr3SK*4l2JJ s4u3K2RSRSJsSn%E )Ey@vfq6І Ff.&FFU?:~]|3O2W 3L7yJ<9u*[:~;sInd}EsiSnO|o$ޒ$'v5usTTOo.]2=^jFIS}yV۔t^tM *9r<Kˁ9Θ5g~~y?헰ξk<<@!? endstream endobj 10 0 obj <> endobj 354 0 obj <>stream xY TS׺>1s@TPSk-ֱΊ2#!$y0PڪUjmnkkkI{]2}كD+L(k$?HE/6G }z<2ێ^GQb(8"y~HhLv_!= 8c':=x H? H%psvȘ!gEF;QQQ܃"&~0f~CxGx0$8rJ !M*";<{iPoa>> ]fQvrKv[~YtdžQnjwޟ8)~˔ӆM3qafʉZ@MS[Uԇ{;j5HEQ3EPS:j)5CQӨj95GmVPxjOK1kT/՗^Qv ޤTeOST5$E yzR[z='Ih(SkI={u}llߡv:;~36}f逭#|s`ÃăM2K 6E]R$['3$xЄaUk4\9b34YG_-φKo%x0uvEW5< fhU WYEp|Ķ#,/1;aٴBuvāJ=;Nҕ&0C^C4ӛMzmV'; okuJHwrP.n_=iZ-1$d+lXdo`ĖƲ,*+槠lc`t:X 1࢓kfMI,N:-i$c123 á93YP,r(Cc;Ei Dڐ "!̜c:$2J{|U-fަUnC=.!KQ5jjd5$pPӿ\9u|5Nn b3 ؔPoX e[ Fz9*li9e* 5._q[ UU/8B7V@-67t@ JxIsy3 Hp}gd!!!ݑ"'pI2 3$U ?(vȟEozc88?.6p=~A5*/V V7:-x0 w0"VA%|ʷ1dIx; p ܴzac0?F4mgPEONT+bʷ+VG kQh֝;Xap5KbXǂ]GB=5uazo)R(ӕ2+t85=ӡ”qTj9wتuT{(Jo;ImWɂHU^ZGcwLf 4hr$`k*UZ D3R:3MP;&i5Av?B@3g?f?f%T9lGnxlwNj)=t< D3~@2Av;5\ >Y7FdҟP;ڰݟG8])} K![I)ܦ>Mc섧)xx;^oF㍼Ck%Trg a/vJM&ӯvkuPǺ`t.׺ RH:GS&}2 ݢ(;v0WM63zzZBe c% 4hG#bzL6 k ̳< Ғ57bM+90\&2yunjj3q7zĢmx Rb&h!Zơ)ȕ_oqx෨ _sqˌwd]ҧƎq 84Bk 4 ϖ76J+=| _;:G;n ]zPU]yk2tW|s,^ğmOj=ο?37q'#C|Z= dPbB .[y;׾l^fZiFSEG߈|~>Ç!KJIp&$PӰrx ^mATz :I$*z=(tE$zo_d︾׈סB,M]agͨazm6q&IdwMҊ B]ax@?.3p4EXnJXufm 1&Itް-?w >E=h,{E҃ DSi 7 qwq6 DkܭDPiWuͻvfW GsةF[_lT $Exc3^,d@eaoHǗ.hk5n,8Ez¤Ҥz(7;஗3a܌ަczb'3ǵƄcka%R U DFKȅǎ|@/HrilC2:d͌Y3ք ~c&yd*~D3Zaj㡰Q4s;c8nm  &̑O/k0F1Zo|fT$Bj ӱՖs:T:}]I2zXrȜɹ$L!d~~9Utwēz/v+ ˤj'0Vkq "_~w9z3mmGHt܈ډ! җ(`Q P`30="$Pj 3ך*֋ؠv..'~YyE 8pĹ}#~5*AwT&)[T2BIݕZSG`3VP]4iR@].b9 /'ڗ?2Ux آhWo/;ٮF⧚K7Ƕ'vHUd?i}Fnh4N B4['eѼmnj gD4Fu3 [>‚ Gϗ^JG@xd!keiPg1Dm8rƵcBϺઈ:e= 4YdB9QI1ÑDh,'mXV܀A!ϠOzO(Eeʁ,P_ T'#V}-ZHL./ٕj+a*L.LH-p+aL%U ~YT'[Y#b=B&?銷p=ꕅu{HYyP9DY B(܌<1ZZXEW@D}}}䍡M~:Y9xR^K=d\9sXB8M*BHGB`=M&Ob[{> 0kuW} eBk8K_E &K c$)ȅ} J7AlQo?آ]#fɍgPO~YB1$;yr vU7B^qe n)dy7ƅS۲&H#fLϖ56 q!\u 5i1iqhT^ߚ` lTG@w'Jyi8~<2c;0IZ_G@U &̢Pϸ9C!Pz tw (Fv,eRL`"q00ƚQGv7;:SU,z߈`b47'f:L@v }HH;I\@;ӈA=\IA^%9t qu##+Z1ڇ]{67 1 SYb^h=:'ȾӔ+f)Yd9@qqrf:v6Ԋˠմ9Yq-WwC ]3k S u >b}0TLrr|0ޥ=3wfWbtu$qk#'|37lW#]a"Q[{]sx4ˢ˿g&Z)icG"[7]=#z`K\ %, ^%{O̩V]_v vNUE4'T/cl_X+ePRAe{A@ a)X]Aj DϔRAc;=T>Q"ܶ T[*ht{NC?Dzιx5٠_aO,RȑϴGufYt*p/؁ڇȍ°ɃǞ8/&4,4PENWȒ@ *&53=3X_ ũ,.Gvh5ۃQBLv^s",]m=dV>{ۜů[LV>[(݊,Tkz}'T+U.04lv֭*3ҳ|qP$[C "f r0!AQʣ : N(Bl2DI `";, |L7-{!ų;%Y9yj5 BVȔJ-q,u d{(QrbմB/D^6+>b~i Y(DOU$ܩ_>/-X|"79(#/Oߵg4 !xMZGHGwYbif-[?1ukOr9aorm* _}wm%<&,LÜI-w5/*|W)&b/z*S> p1D9}= p1|t3̆D)ŏ_* UhBQ[l"˦@4ګN?&qR|.'e/QQ//Pk{ֿ?lw9r{hJo/;{: ɤ/-d磠/m,hKQFU~r 0kWZޝD8Hͳ OMYB p({1Gx& ;2luloTNӨ5V2??2ƽ\7TshmBjkQzɮ3zgBsv͙$7rlct`;&`ZN'%WɂlWkR4THѤj`'#T(; ݼh 0mۜҏdif#aB  n/A"dy4^~sx5hw'hA٩)vbZxW35Cy@#+.Y% DMbl,GG=~@ˍh?n1Vv|-|96(RIC_~XLՐIE%oZ 5ۥ"E&9gvBJ c ([KO|`ښSM%N^>a[<9HB>0 X_iƢ2鯈{$\+oh7ߓ9~X均` GK v"{[E,ԯXUrxcɮܽg0dҗ؀bNڹ|6FmaPo|]Ag1m%Of6fbO79m%Mx3ZH܏;Pv Wkϋil AzGVC H~]M;# ZqubyeeɮֶΝ{o"KM?F^rCt#1ʿ`sҬ`pۂ0 cD_{ ;&k)Q"$<-5C`w9'2*U8PAa / ^JBg[N*m_F (0ðyzDKJ̟@r- &'TXӨ`hT} nݺ+}72>ir†k8qx#py4Q͝smuMiΣysdݝ_[芸eQ,z}Vmt[t;g9S6=|=6=[ɏz p]ah8|uݡ܁RsD<.(k %{62bk7Ǹn<\#a;䤿3 [!|L3A+*k)lCаԵ c9le>veb)h90k⿴ ("(1VflFrp?|ywz xlO_?E6ۭ-cQ°E IV%F14m+7KQp~Q= hsK^=gf璡O_oE endstream endobj 8 0 obj <> endobj 355 0 obj <>stream xX XSWھɍZn#bmֱ.jK ʒ@ @zKv KPTuVk;]t::3a{9{{Myxxx%G[[rw2IJaBUĤq3%jI'Z",/ZJ*4,9ĩXD5.O8uR)2J".FNx콷&KaKJٺN TJ>߮H۹)=qW<*3)#-ccj { {ۋmcX8==aK ?ۈ=6a˰]fl9ba l7[@ Ǧ`S1/l&6 aX=MtyN46ykg HASߝV2fʙ f͢f}AM ~plsg7}'@@ڋƗv<,8χP:_ZmNj4ُ^&dv:-ݦF,nā̐SEoiOM%B^stռX!aיwnRkM5Vori\0 M402-bPHVk 5R _M7Źμv`J FmnlAAnj2I-FPfֶzuzf Khk~@.Iׄ?<ߋex01}8K@6OS\mȮPp2R@Sݢ5YZ z >uNL YZ][E>|Z\cq-fɕ0XMR騶 PLn45amb LfZB(V]B9Eq <NX.ѡmr `3u5"=h;[k%P?ゝp`\FWI@[|'K&ʋ Ѽ }!0s伽q$.K/E*7LN. M eW#nGqQ1],7͐ G@CjگtW[/uMv{)/1q0'7`aH"('fpݾDP78$ R:bW)f>K8Ļ(At}.7g bښdr-)bŐփe 2>( &:ho8f9ґ&; jnx4ǩۏT} ㏦a.0{D' X.!‹cO U K6`)95!;k ~bˡ5(8,s^. 4֣,!b簟 ; h~ľy9Z+cޜDW[zބKSL -yJ؃3["A"fe,.2&vO7rgauYOR T @/-&RzybWrtԜ`sa D!l2vCp/pѪ~w׳^ ?ጎS4_Hs>=a2Ǣz>),, LK/8|tR\q (S8%J:&0.Qn+w)5e>1 {!\ou: :AH~,YE8Yҝ#/B='>қqK5&ռ|~(\93a~fff@V@ 3;>\һùv)JbY1yj]  ?To;$! C|Q0KhL(QI%8DHjppG|8AOݛJK7Fz\UċRv]]@pضGnZXۧDohB"|O SŦm`.`%|䬻ꈔ$] ޶#mFqC%gl\5ǚh%oρ)ƶ]3Bf 6ny!k`eQ/ "Ld}MAMG!<_704tGlz:LMPùփ:pҌNcwz pnMkeXLyHGh/$ S+OMt p @5>aXS ߳w} ˚Z 5^W*G7,d A]WZYV]WֈtFߑUSJ~kPAVHn%cSxJV6![¯yl3v*BCqEs>ĕHҪ)59)ReMh@2*h9'qr+ú1LxU[@R)i$YvZ֙H$ĖxpN2Ncn|R<,Bdhkm@f7}FK!&'_# o7gd;v3C1Nrq%dRwo5 /ǽX^9u._U%j*CaAq-P /N~ۙ ǠfĻup&|L>ߙf~>ژiIT!莈瑖ܿtʄj]O]dAQQ:quY#yIb $XS")΢yvQ𫳔t_O=#s@X/`#Z%N[)?buczud?1lҐW ~5È\̨ xntg!tXp2lv H5.N$tMH,k,$‘|ZtU Oh>ġxIЏGhs1nc䯱PEa!vB͢v{We+V^wݮ7F4V⩈ D"f;lP(ޟ\;R.UuIw7?A_u\ckd,VRU4|7S+ZXIxGe-O8|X샌LcSuKG{g y~֪E&JB .{ ]^mG8fU%t \=:452Z嗚jo-"GlNo=iqM+-(QxO5zy/ 3 S"rjGu(-'c230k&Hl7yl-ED3%L&ݒ 1@Rd;+jB`z၄Ĩ.@w@Bw3:p< z{# KհW$u+CY>Q*n?h7T7!X` ;gŋ[RAqMSk߹brQ25מ)4::A'?[jAY@DMs<t 'ݞs]n=nORV]-8gpjf0)A4;*.=e'vmo9zYnASzpʍLDX܆7` E4Y>&0 ? 7W8X;~QnH~\eqM`QRKHX:`CYxZs5.EOǝq W~л^9\u&,*ɲVg)PMEmI5:|1S;)F^gz"g9围hjz +#r7 YJ9;@)Ppv`gp3.&"$\IeCZ\UX\XIVtWVY(D[hJZ ͵ T)`4k-8G(5X|_Ά2 (cШ !0[ʁ]PYpx(\tyFsLI C߸%c~9:?2SG1|аk^V&U$:Pn9N5C6Z}JFj(4wKJ[uW-"YX8p`-׼} 3SI@txvPVw7F@Ċ3TYr3%or"h$߱OQh跔v]tF}٥p w{b°OT}Y5Tnm,[Ku-^?ׁ7 1^k+J[xHw k<-bFsf94~~2ߝJ{ėhK)0CQqqB>O#ZU}6)k&|(7 ]8#rv ~mЃ$0?Kvֲcm#]e 2N6# wMn7^xN}%O~(TH^RIW^ v ȁcsixIlT~*P !kCø@Kg]#o<ޠɆCzrl4M:[kADMhW뎂AӠnׄ) [A`m)%vJ8d4鍜_yRX51+S6lޕ=D.2jD?;[w)n2j)϶5ʺ OVبgRޏ[_.Ly%?'ysBCY_ir IXŷ9{kzuyQRiTTow`@5h, G8D׍-XѤUyᚣ;mz֐_c³WG긐[IJi@OUewnkWk9ö/7##ZB~ Cuu/Ѩ=u&Mٌ4kOoufcuqŨf&$_;E".K~'Oɿ]ki .T8sppk _ endstream endobj 100 0 obj <> endobj 356 0 obj <>stream xzXSgQpu=p NĉI{Md@" qVq+Xڪk}m'~ I뻮9s9E?ᐎ..&ptcqPK`V c'& m@ס %9 B~b۩^]d ys, #\4b'D|N" b1Ml"IO V 1C b(1F# A'X&FˈQrbaC&1 .~<7_w;cam9Tw$wo0lWZib6yH!C][2iÃnuAU@Ej.djcZYBz:> P[ցZG {GF yy9¬(  eN2lT_jzJF!HSR 4Uyb-Wt_$컂goX^W:nPC4=V:nYŽG4_ eA/:5Zx" %TD1g2(>ՇNjVV2jC7ѩ8 m|j@0vq'"?TCE-TaD3EfNFѰ!K8A>h6|7n߾`*GhK9-T豯릏H iQP@!ԙ8?wygpmݺMh^=˅13YjA+'G_za%^f@ $t ?;&r5&8B }v1j-UHbzkfB#'UN r;ó>UjU_!`u2 |dPD\Mѥk8Ǵ.Nw.d@bOTkEChH>fƅ3DNN쥐'orͮ͊Ȋi8R"Nc i3rCn>(} -eÁ/0(/su9k7yr1gD7p Kru+ZjϘ?La8D8;c㢥p)4831Rng5^+5-`  PJGc؛Уar, mm~6jTe-,[Wh!CѦPt uBfc7RП*T9\7բ3%O@]\ւ`5;ݑ#-,rcͥG,&O p:"˞Z'zHD"6dշKiJ>8[yVb,YM/?wgegs?eۏ;fWٝnv{ւqn0*ƻ6Hz1yLaXW(UmYW@̊3=Ӎ鷌WsV~iƾlk2^g%L=GY$1Gjɑ& %u"7{\=`']õW p8 "yы_ `.Oxu߫>pGy}i .4<|Qx'FUq&;\BҤE+͒Vds>. w.ݜn-ܪ=| 'A.6ŵս{O'(ʢ"y"WTZT =&wj"?U  XP! P!H\Nl&XnMu;"GO@ h)k__uPS*Wu]'(cS2}ԙ //UTI(4^=o:ylNN@O74ؔvR:y3VؽŰ+||Rݗn8udJ4uػi4h!ߐ5^_Qւbhw%H=-0#H#:Q&$Ɲ#! ),Q*1|@ك}:.$80H7"QpZРV70MDAI& eo\kOÃDɁC+p+mk.HbyJ._/)cz`+)eG# /.j-dNi_bO1'Y~[P>!yr~W#8M9}V¿ߨ1 q}b2b"ot 7|.} !9WCXD ro-U09!jP {sƭN ?\x ~l> cvi& m0k6xVT2l14 F''Cי2ZMN@'զ>#*`jPJI;jKM ZX6iZD3xKʘ&OE1L%ށhėƾ쯅n8Wuf43rNWW |VS/Hɋ_x i/e4 '}RttC22&S{!Azt.LiF o6fz=f'y|eťkʋJJNTwgv qH<afߚgXd L&Z(Is и}PexryK P }\X[S룳 %*# j A񓲲oh bH(oY@Wh173?<*( U H MX@=SFuE4BVY{rTPA<}uN"zddٲ4>дjX.jiA<_^()>2SV+5ykM=713KZI8?Rw䜱7pfcFmZ^]?*S/3)+VO%(A2K(jǍ}KPdUeU葺& 3nB]?\w"EȥQaɑ :NJ4j^]U,aZݮn:NRwPVT<#SXSw~}i?U۶yv;0' gq=ZybCБ LbD9n߄_x;(M5[vurfBBew厣 LyԉunG}T^|Hfh )LJ@lRu)) ЉX[jZa‘W=E(ob}xZQ e }&MKHQTTYLy- y^(A@֔g鑳XNfE4(OKF3^ghϽwLrD۹#b\ QrGQʇ&uAEf џ;#w8:@,K̕2N~[J'0Cs@ W]0OoJ7[%z܃@EJbdpfvE&$>r3Z\~"J$ũ%)[. q@bJ,-^R؄GU% -KmRUQmiJAB>]=R|_ʅb72q Ώ)E q9 jy)]7,8!Ƿya`ra2> Iy ͆UyY&ҧLi#K;]T lAz,1nшt#f23:a&HҔ]ےd(ʩsB~e0k81^n W& `4}CJ dQelEM~yQBc>lq>Oz'- S3bR@]T“{!ޱg&3Z}$sG!KDND6hr~FAKH F zDׯz:|'nD }k`M^pA/ Sp>+68JA1&v+ /V$I TL9nZN=P2l1THhj=TΩt~|¥pẢL6Ցei y%% )I.L,YL.9ʲjU|~b^/_hNa~X/Mcgebp 3J1UOu\]ﱑX yQWӡ˝Ox^ CX#IⴃILy˱ ztm-v}4GJ Zr`)֧k*C+AƆ5v PȀ:L DBF `'6\7I%k&{08_stanI^HC Tdd(h-jFS,.V(ŠĈz5ܦ{e8d-g'VٲyN"p1 BP MDVtbp6DCypzh~:<='=iu$;6/  23G@U7!vtR<*('I6fo|CI*gH!HK(a|nRj8?ϖ?fV McQ%/5f07'8ٯټsWy[$_Jâ 8,wa?8ן җh@Gzak׼`rM+9Wc-Ͽ0Nf^LgcVa.Z iEIii VC/NGc:48p+h !rͧ y68׿{6nsc$WuxnV\.TTD(M8$GRuNf~ZkV?zNN& a];{\k: 4w}l\)Ig"o+psZ;* Y>gH~@RbPFDUGJB\8~wddq{*O]ܟBӹy v[ HLE"+Oi ڴm>Sk ]!"syځ(UjA?R! endstream endobj 98 0 obj <> endobj 357 0 obj <>stream xX TW֮RR\TEd4Vܣ &Њ"ui6ٕEpʢ""V8YLLf[#uIfQ޽V0B`Ym7R)u>v нvɷ883HCmg>1k287$-!8>Qbsţg!7 Y,`& nc',.[Aie/Wuи! \'daWB0EͤܝFۚ8&H2ٗAqgp!mva 3_tc3$@\`+d\ ab |/cb$<Ա3oZEO Jqg}*l7BI22WRhpͥB1ը5IF#'>)Y܊ Jbu]VQ{ނK[qo=nlZ)&a. [l#t .|xm}j_{*\2S$ZrY\i b^lBmf q8GW n6jGכ6{6Z_MѵpHBmκzY|[Mjktѫϡ:]~Fv~unʍ7KH/5f$75Kɇ65580M(M&!Ƙx=•CT.$]LO-Wmۮ+_[ UPM7HD@랔MIIRdc(|Ȁ;w@$cذ)0W\3jy `hmm[е 9:S.yoQ쁔o!b)ߓwE8`#JH zȀm|eX}FcYi{es5w/,$ ZY/TPޭ8Sur) eذef.}L(|IqձKˇf ڞ##fOO&A2ƦywSWa1%.Bf.U6 T?LϿJ/,7 N *17 Eˣ/$)-4G^ J9)ϩuYۆCy 7)n`\}L(1 ;!lWaZ9|(.(L9hf"dȑ hL2vY. η(;JyN=K"VEθ PK_hK:ݧ^Ӵ`ZiPђ"h-UI)9@>#:ai` ݙKl[xbYdal6m1b= sd=gwyc7Uq|fyI5"gfn]qC#&P}tC! 5t?dI$Ku-FEٟ2]2M-RmN`:O./SL쬖􋌊iP,X4ʁ[|&p:t#=nV'2vy'B]kp|3w,$ 3Cܲ Kp'ML')Cdh0q+lOOfhMu9;%Bެ7v ԘlP n) wa0'is8A#{S_ 3#ޘ{8x^&M4=WʩTs#!ٝPb+qFU-=хPOړ抵Tc I+q<9 ްΰl^% TAjJ##))[-ӿvo]! C.|hn[(җ4{5͆.|/'ǺÛ;t&\+r%Sn#!g*&~"^fU@-[@at61 K ׮l5|LN"@:8iE>Z(XeE@7u6^u p{]os8"#47قs$ЧqsA/QnUy41$j5Ǵ> endobj 358 0 obj <>stream x=}L[en\L ʊV+ &0FK -F/0ABC ݂BMh#cDb|o}!Z$sNrN JYYђY *:Ri4K_;|Y;JJe&~[iлpEj2[-305f#`QQZiYeHupd9oHAC7u%cYYf3M1{54tU+D}hYC[E+avwEJ pBjpOh&&Tw9r)L\JC[H$DLrvڅFW>nm >\ӄU 蹕vEi^dR8hj`fLՀ^JJJzKb YXe-k8 +xIHo.U%¹]˧]/.[`U;~}1%&Wq&@(;%{/.>u|~ MhlIrGT<3ɼ1F> endobj 359 0 obj <>stream xY XǶqUel5D%%& *(+ ̰ L0þ)+KD(&1$6}0Ln|^>T9JeчDE..S9V!F^HAr%#+Ƒ6(H(xw'~7Ι)S/ w #u;|" 8yB:)Xޛ 0^^2NAa=썻d(8pwx9x,%Dp^sE6xך%2率>k[$wUx_m7'84)Sߝy֖x8R[(j>D6Sk%#5C}@-ޡPoP˨XjGPNtjll'ۮbhrV#z䰑kG^~5kʁB% JDzHыapmPcS,::֠S4}|D>H!Iu/Ġ(ED/=plqVtͫ3{|^ |Ñ7"!ksB;.A(%:AHRb#,@̬E7?Y%>jTkFxxtl`xFQ'5b8"XqމA)AN81 U9 2D:TJݎ|`BH`5V䕝T\Pq^^qf7SxI _RҬEM2uvL a;]gbA o*;M^8B{٫^\8cKytc-yIlF R#|yU_"Ym0D':jùVVWak @zenpwia&̘ %'XA,۱fpŽ$I?}(R`YIx jwhJ/yo n8cm0921Y">֘&J{t"")2#0w{dwX0獝@Ӱ&c-Hh<\]?B`SkfC{BoԖbD 0LEGܓ9< <@IAu5'mVp-=,}8Lz dO0K-S RSZ;<{U.FS+] #2,p2llp1P?a%,f]=Ops_Oa3UĆz^[XU*y/bʪ "\7}>[DRLG'G>ŲhgfX C`ȋ+ߴFPzVNE: Ţ C5(eege?ʎhy~s)Gwhmg$~b,_`Su*3f7A.@7LNCȔee-+D1M?~UɥGeD5u^b4ez²"걒>iK2v]lYWpOƥ ƀ6~$K[ 6ﳪzBӚ:K1V]Rԥ<8Tr`o5So!%ecwlIא )vަ]ySE4V!yp?/1/PZ*h{tjDr< X_X1W?>LJSB TI]Q٫(/k* mtՉ衶KxU]dISŦ-8(o}۽a*3rj |W@1OOP1xv«~v* FsCFdi2[6c^3Dz ;?Q>~jyv^K̼Rg6l)" gT1ʌ\-< 'Md1>T\Oy9sJ{]7o:>+m[37xSVγ.\].F.neNqs>w0P}@"~ݹ3垅^-鶓_[9\fxA۶I L⶷oϝW$}OÊ jyd}o+L̈́_=Jo'6ZTs ^\}I51.Aw8i!thokN[ =+n+]L.3IbYʬ0թĔ<`( Չ"|eF$I/ߑ]B^5ҟl 15H,[̶1RƳ%0:fimMf5+_~Jdc~&"hz7 WcO?NnnW~h3 N~c6bA ba2EFGPFoħ-tZmCWRv$\tnpڲx"z?עF2 ˌ9r]ͣJ&vk} Q!jEY̿bnfV^pffڛ2Sut6:\VT@L}w噐Cx̶7@mtuI}~k:5E(1 XKO%{Ɖ×^]+'+'x"ޖ0$厒}Gm߶Y:M.eʅc ?v ch_]1/yB%,u`g,U]@&u6,8e* 1L7|kWXBE36]ҽwv 8Ӳ=xUVZ:7iDu!cd,5Zߞ_0vsڞ~5m x<ϴaz }{?o[[M_;̥vo5t" Vը@7y_x˻xd<yL"m8tPUq +%=_&) zZ؝\r?H@ehE u-ZQea+$V@r45rG54f3r `F;u]@YVDZ,,mY=I)׶&uNbUJ$I@ $-$Q"`o~w8zϧӷ;5>$d枃ج$tU([]P^u;ض 15Ce~3wn8]m]]%%}RA[y'}vP&4Ȇ}!H I<"b.uQO?)y7/ԮL"a)G5(<0 = ý+lk`, `WcH󁚦k?- co(E$gta jiAq]c-Ox n PZ:.ʧq>ǧБx&ӃhlҐ,6e6fp0WYiƺzE$Q&HTt,>l .iUSzdA2j0 nWAxÁШc]A6278<~/~%YJZcDJ\\*5->BP0#+O-8s(8EbY&b83|pSt@p -GⱋLO 7~$RO:Ώi%lggB^E61)%)C񦧶 "É?=rjkKqsf/V%r%O4G̃ϷN_'RBXn~&t"1))\`pHsR~lalBv(ELP8dKK rsrb4EqE~TK4% ٺhrkUN_r?8i.jZRwe[? "(+xG٩')\Q[)kl>7a89  _;pN*!(  hgBQrY#tj:WUr+O}v3.2@peFtQpÐԽIeQDE&e%d?e'EU";MIYy^=9J/_Nfbq'2tUgsT*o{ %.t>~.lv[챐"X~H}+܀RJB(5+%2.kgpS.L s^÷LTeQp高_;a^#s%~\?`:++?, endstream endobj 85 0 obj <> endobj 360 0 obj <>stream xY xSeN %ЈPADD@dA,]i5M6m=MNeߓ.I7me);b 83<\O="m.g(lͦ2b'am(c`&n3S&#.m$,̹if.^3^h̥yQZJ5)Ҭ)~;scA(CZ6s/RS=TZZ0%ha$ygY37deHJ2gT/jJ^-~YV'.fHf)Hϐs8w^]&(ܵ\RQ hc%9WlY-KNx _Yy!lzK 99s6qVrr6sVqlSE d!|\S$P6ij[ `7#ޢ6XM8UH4'Z_YAa.7fg };d}`:a «P ! PHqy_X~{$$@IɆb>ڈxm'í{8Ҽs]r융TגqsUkqΣyɁ+ᩴhLsu* 2 V`&׳ʊ)Ǐg<޻="G)Β P߇׋Ne6WWD@BS!g=^}M@Нn=CjQ G{ uܛ2FS%1q@>g4(o`[]v ,UE % 9!PL1;jsP.h 'G'^EXŹGF2t.[܃OȫVB0dMfzPht}tNxUrPvPÞv>G5X][:; HUNZ,ovZ*-7A9tu.К&;jpu"2[JpR& jIЙDk(6qIi jOD9S>[x;c p*7plnqZWmIesbV>وD[ejPM>N^$O ᢙC=f+Ԙj #k_~)s[THE@mqעĨ): _NJPm,) vA(1u}a?D@[[XHO,w/Ւˬ0kۅrF%Ʉ/[hv,;P _=~? UWͦKíh\pAxQf^g;yww<rʤ7GrY1QL4eE3s3TDh)ed.ݰ p>/D䔆vI[GS.]՟BSomL䈟]qLNs>L @<վ_OI`Yt>rrS&Gubjgy}uoޕ (++/*PO&|P}6jC\J׳bi B龜?XC󋑦28@|P3ҎEF!ɖONƇ@9`n3(&]A&u^Ar&U󗼋}葏~dnH> -(X6&֫8Z= 0^UqhJppG1夣!E 7]]S!X?u&ŊB?V6siat,Vۼ* MiQ6YPy|ǫךW,-4ŤY1v>G\23V'qiӯIG3SxZA,:OKoq`;}VWJC;; J``XqXvHy ^#]~ [R&[+6Յ\刀p~y+`$;~zoQbN@7$Z5]eI[SD䆕ryVyba" E'aIa-b릎Ϣ6G3gx |zʀT Ֆ㓫r4Bv•P&ihT@8_E{+ \.A BѧE;l;ǽcՀ;)>cTDo jXV&hGCci^Ϯ8v|[`ڙɃXJBeϮ]ᦆY;xn$J0Ф^R\R[X$c18?yp[;ы f2~YNUΌۭ 8>BD.v.gSX L#qDfad (f 봹-jG Bo np*s@.5}11',&wA"4F GZ:38hY U e`{n x -z-=ֻN`2: -,Ȱn"A~&er%5ۛF#^zXNwڍf# ζ9+0œ 2NqN$^['B2n{ӿʴ\f4u4x^F'WxL> MY9ޟ){LCqfvtR堚~|o7-Ҵ"v.Jj6ߐ*yz-n2EPlu{ D48IIv>ij2ሺ#X(cS(;(߾Yw{xӛpi*NZ߭ihwGꏴ߇K/V!直*6!j7ztn׵˷ܙG.lM=[h{S} y2w2ӚT>oh4@ǧ3INH#nA|UP&0aH :>+2AƸ:TTdǓw~"> endobj 361 0 obj <>stream x%kQu5*D#-4DARP"q{*Yl6ټ4mi*ՄP=? y&~98x42<YSȺ;f)KoS&lހI]iQT˖te=E4᧳8 KUIHR*ۤ&)2))Bb@TM__E e}CNWZע* Ejj@dǵgj]J98t^8>!9r|YUcԷnVϸ'!c։;F-Kge<[mCwaLd\6 ?%;ZJFhz!nZm4zXr&7{6L7L~hAVڬkL=0`$hg FX (6,Ar@ f_-m,wߝ#/ָ9a^M8nr]1\.[ endstream endobj 77 0 obj <> endobj 362 0 obj <>stream x Pg{fuqT ٙ!Ԩ <t@008\"*0AASlQ#hbţ T jq65~n6ڤ*٪U>0D!s_="1o@. Zg$)Hd؛ʐj֛3"g.Zpz"'q:cL6^5uqZ[3g|7{y%''{j= e3gcLzu.QgLE &zmN=stYeKk(1U :ctmFʗr6Q~fj-D}JmQ (j%$M9PfO01;{:HWIU*g_25i1;* J щ8nKb/;Nж.8`=|jUX$8.\ BXH=7s3m߻=vjp6+HU)43c )Q!\7*e#s/q2d1ߊ t$ ?$.d? Jr++Te;*:U+b 3>@("Wʆ8qSS(uTlȆVM|$T$wJ<>OȔ?*yTp$HZ p մ:mlAˉ>[>dq#\:ߜ:9i}fUuB]9Zَs5mm%ucFY=#8-GHz2gy dOt6];WgPjMLDcr]]cE[ꂕ._ 5 <"avv4;5~b\bx*. UDvHq1{Ox.dX2OԜ*JkKw(SKY-(h z$WH?-6#we3!=+Pg]ۤ\fvG8 EGNcz6㶋o߅R5N-ڇx@x809g늁cz_BٓJ6ͩVY>l(H`'4Uܷ?dlt]{<<)́$٤"":2ODyWLnת}QuK ?vHY;Q*F)HAh}}"iTXBuM&% trkaq5 giއ_wx\BM4l{UJCxf mmƌ\&#ԏdRh*npb@ MڝzΝ{a up`'2 -Tk4%%EOwdFz-Op ˵kAђ""e8p:_s#G. "ϳҏ"PNU//$NS L\&326;4Y,ñiN=q,)`iqa}p\kF*=%4ٍqݩ.I3> endobj 363 0 obj <>stream xTkPTe>r$IJ$dZs"!&,,r۳,gϾ,{" rRl&)qђ5m_}>CQIqy9YK1RX%. /c A ëbP ${-'D$mVJB+Yw`$sӦH226I^%yRBV-FU"L{QlNOKVkTjHZ-F%T|iLr]%[U]S%yr AYFQ+& FdDQBFDHnD1[1 9Q0BDQȷ(LhD{Wp"NuQ"JBkP ʱ+g̩S@w_c*w@% tpzD뮉c-bk6<FBB𛐌bbނRCvbn칽&#ga^TƦEjȋ^=~埀Bbf5Zs#Ʊ.ج=v:P_7.nƪ6 V|'}>8|5t)f"UH[{.oNn[;Þ*A ;ktBIpq̧ bo|XEI2UUg9ҢIJ ~"^B'E5GQ5Ye߸4Lf52%ٯJa|L0xmd@P$:}]JRc .璄z N?6M`M ^Gḋ.=`gFm `]j #4غcjaNw nޘxoM--b8]@D oѳs~۫(HHrju6}' +un{ñ(j4pkSл\qK$ڳK8.WOtN 0 ΋lxڡmÖ'ٕMzs8`hussrwtGg!oNhɰjxԝfk9UdhtzLw\iRA8ESD/<"w TwYeT7l|,`ۓ=@eO|6z7ȸGOMjwf(& >kGv ^mר tLeVs)S G#n&:CuEk랯Wm̿aB\ *!I4FyGm@[,3J_M$9%kf8͟6s>Ў *΍I&xqz>sfY̭G}>p쒲B;:*[W&/Ӧ+vVUc{SrMkxk%Z|=NyScAϩOв;KHKEe>FN7 d{;{B7 'Gl endstream endobj 68 0 obj << /Title(Index) /Dest [67 0 R /XYZ null null null] /Parent 22 0 R /Prev 53 0 R >> endobj 76 0 obj <>endobj 2 0 obj <>endobj xref 0 376 0000000000 65535 f 0000108839 00000 n 0000212247 00000 n 0000108559 00000 n 0000103118 00000 n 0000000015 00000 n 0000002707 00000 n 0000108918 00000 n 0000172475 00000 n 0000139635 00000 n 0000164354 00000 n 0000138954 00000 n 0000160087 00000 n 0000138361 00000 n 0000150013 00000 n 0000137231 00000 n 0000144481 00000 n 0000136612 00000 n 0000143913 00000 n 0000136376 00000 n 0000108959 00000 n 0000103540 00000 n 0000108781 00000 n 0000109659 00000 n 0000109079 00000 n 0000109324 00000 n 0000109201 00000 n 0000109429 00000 n 0000109538 00000 n 0000103928 00000 n 0000111563 00000 n 0000109802 00000 n 0000110932 00000 n 0000109925 00000 n 0000104133 00000 n 0000110032 00000 n 0000110174 00000 n 0000104330 00000 n 0000110298 00000 n 0000110428 00000 n 0000110561 00000 n 0000104527 00000 n 0000110684 00000 n 0000110809 00000 n 0000111201 00000 n 0000111078 00000 n 0000104772 00000 n 0000111321 00000 n 0000111442 00000 n 0000104985 00000 n 0000111841 00000 n 0000111719 00000 n 0000106498 00000 n 0000113289 00000 n 0000111966 00000 n 0000112915 00000 n 0000112091 00000 n 0000112217 00000 n 0000106671 00000 n 0000112366 00000 n 0000106844 00000 n 0000112501 00000 n 0000112651 00000 n 0000112790 00000 n 0000107017 00000 n 0000113064 00000 n 0000113165 00000 n 0000107356 00000 n 0000209945 00000 n 0000208086 00000 n 0000143639 00000 n 0000113443 00000 n 0000113473 00000 n 0000103378 00000 n 0000002727 00000 n 0000005075 00000 n 0000210044 00000 n 0000205719 00000 n 0000143345 00000 n 0000204883 00000 n 0000143037 00000 n 0000113569 00000 n 0000113599 00000 n 0000005096 00000 n 0000011349 00000 n 0000199134 00000 n 0000142233 00000 n 0000192542 00000 n 0000141757 00000 n 0000191166 00000 n 0000141437 00000 n 0000113675 00000 n 0000113808 00000 n 0000113939 00000 n 0000113969 00000 n 0000103732 00000 n 0000011370 00000 n 0000014556 00000 n 0000185891 00000 n 0000140852 00000 n 0000178403 00000 n 0000140262 00000 n 0000114067 00000 n 0000114198 00000 n 0000114329 00000 n 0000114360 00000 n 0000014577 00000 n 0000020829 00000 n 0000114461 00000 n 0000114597 00000 n 0000114731 00000 n 0000114871 00000 n 0000114902 00000 n 0000020851 00000 n 0000025643 00000 n 0000115010 00000 n 0000115150 00000 n 0000115284 00000 n 0000115315 00000 n 0000025665 00000 n 0000031965 00000 n 0000115436 00000 n 0000115564 00000 n 0000115695 00000 n 0000115726 00000 n 0000031987 00000 n 0000038010 00000 n 0000115836 00000 n 0000115967 00000 n 0000116103 00000 n 0000116237 00000 n 0000116371 00000 n 0000116503 00000 n 0000116637 00000 n 0000116771 00000 n 0000116910 00000 n 0000116941 00000 n 0000038032 00000 n 0000043783 00000 n 0000163639 00000 n 0000138714 00000 n 0000117051 00000 n 0000117188 00000 n 0000117321 00000 n 0000117452 00000 n 0000157852 00000 n 0000137897 00000 n 0000117593 00000 n 0000117624 00000 n 0000043805 00000 n 0000048576 00000 n 0000117773 00000 n 0000117908 00000 n 0000118051 00000 n 0000118185 00000 n 0000118216 00000 n 0000105190 00000 n 0000048598 00000 n 0000052900 00000 n 0000118326 00000 n 0000118460 00000 n 0000118591 00000 n 0000118724 00000 n 0000118855 00000 n 0000118989 00000 n 0000119119 00000 n 0000119250 00000 n 0000119281 00000 n 0000105428 00000 n 0000052922 00000 n 0000056887 00000 n 0000119378 00000 n 0000119512 00000 n 0000119643 00000 n 0000119773 00000 n 0000119804 00000 n 0000105634 00000 n 0000056909 00000 n 0000060527 00000 n 0000119890 00000 n 0000120027 00000 n 0000120158 00000 n 0000120286 00000 n 0000120417 00000 n 0000120448 00000 n 0000105848 00000 n 0000060549 00000 n 0000064556 00000 n 0000120547 00000 n 0000120678 00000 n 0000120808 00000 n 0000120941 00000 n 0000120972 00000 n 0000106054 00000 n 0000064578 00000 n 0000067749 00000 n 0000121071 00000 n 0000121205 00000 n 0000121339 00000 n 0000121470 00000 n 0000121598 00000 n 0000121732 00000 n 0000121863 00000 n 0000121991 00000 n 0000122022 00000 n 0000106292 00000 n 0000067771 00000 n 0000069787 00000 n 0000122108 00000 n 0000122242 00000 n 0000122373 00000 n 0000122503 00000 n 0000122534 00000 n 0000069809 00000 n 0000073519 00000 n 0000122611 00000 n 0000122642 00000 n 0000073541 00000 n 0000076731 00000 n 0000122752 00000 n 0000122783 00000 n 0000076753 00000 n 0000080548 00000 n 0000122860 00000 n 0000122891 00000 n 0000080570 00000 n 0000090129 00000 n 0000122968 00000 n 0000122999 00000 n 0000107190 00000 n 0000090151 00000 n 0000097423 00000 n 0000123098 00000 n 0000123129 00000 n 0000097445 00000 n 0000101923 00000 n 0000123195 00000 n 0000123319 00000 n 0000123440 00000 n 0000123564 00000 n 0000123688 00000 n 0000123811 00000 n 0000123933 00000 n 0000124056 00000 n 0000124179 00000 n 0000124302 00000 n 0000124426 00000 n 0000124550 00000 n 0000124672 00000 n 0000124795 00000 n 0000124918 00000 n 0000125043 00000 n 0000125168 00000 n 0000125292 00000 n 0000125417 00000 n 0000125539 00000 n 0000125662 00000 n 0000125786 00000 n 0000125910 00000 n 0000126034 00000 n 0000126158 00000 n 0000126282 00000 n 0000126407 00000 n 0000126532 00000 n 0000126654 00000 n 0000126776 00000 n 0000126899 00000 n 0000127023 00000 n 0000127147 00000 n 0000127267 00000 n 0000127390 00000 n 0000127513 00000 n 0000127636 00000 n 0000127760 00000 n 0000127884 00000 n 0000128008 00000 n 0000128133 00000 n 0000128257 00000 n 0000128379 00000 n 0000128506 00000 n 0000128633 00000 n 0000128760 00000 n 0000128884 00000 n 0000129009 00000 n 0000129129 00000 n 0000129252 00000 n 0000129376 00000 n 0000129500 00000 n 0000129624 00000 n 0000129748 00000 n 0000129873 00000 n 0000129998 00000 n 0000130122 00000 n 0000130247 00000 n 0000130367 00000 n 0000130490 00000 n 0000130615 00000 n 0000130740 00000 n 0000130862 00000 n 0000130987 00000 n 0000131112 00000 n 0000131236 00000 n 0000131357 00000 n 0000131479 00000 n 0000131602 00000 n 0000131726 00000 n 0000131850 00000 n 0000131972 00000 n 0000132097 00000 n 0000132221 00000 n 0000132346 00000 n 0000132471 00000 n 0000132595 00000 n 0000132719 00000 n 0000132844 00000 n 0000132969 00000 n 0000133091 00000 n 0000133214 00000 n 0000133338 00000 n 0000133460 00000 n 0000133583 00000 n 0000133707 00000 n 0000133830 00000 n 0000133953 00000 n 0000134076 00000 n 0000134199 00000 n 0000134325 00000 n 0000134451 00000 n 0000134577 00000 n 0000134699 00000 n 0000134730 00000 n 0000108281 00000 n 0000101945 00000 n 0000103096 00000 n 0000134807 00000 n 0000134930 00000 n 0000135054 00000 n 0000135178 00000 n 0000135302 00000 n 0000135424 00000 n 0000135547 00000 n 0000135667 00000 n 0000135791 00000 n 0000135914 00000 n 0000136038 00000 n 0000136161 00000 n 0000136279 00000 n 0000136310 00000 n 0000144124 00000 n 0000144818 00000 n 0000150501 00000 n 0000158090 00000 n 0000160369 00000 n 0000163856 00000 n 0000164844 00000 n 0000172860 00000 n 0000179003 00000 n 0000186238 00000 n 0000191404 00000 n 0000193055 00000 n 0000199479 00000 n 0000205126 00000 n 0000205962 00000 n 0000208317 00000 n 0000136523 00000 n 0000137147 00000 n 0000137751 00000 n 0000138276 00000 n 0000138860 00000 n 0000139479 00000 n 0000140178 00000 n 0000140759 00000 n 0000141319 00000 n 0000142687 00000 n 0000142805 00000 n 0000143226 00000 n trailer << /Size 376 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 212441 %%EOF drc-3.2.2/source/minIni/minIni.c0000644000076400001450000007006113164710027015370 0ustar denisitadm/* minIni - Multi-Platform INI file parser, suitable for embedded systems * * These routines are in part based on the article "Multiplatform .INI Files" * by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal. * * Copyright (c) CompuPhase, 2008-2012 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * * Version: $Id: minIni.c 42 2012-01-04 12:14:54Z thiadmer.riemersma $ */ /* Changed to make parameters case sensitive */ #if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined MININI_ANSI # if !defined UNICODE /* for Windows */ # define UNICODE # endif # if !defined _UNICODE /* for C library */ # define _UNICODE # endif #endif #define MININI_IMPLEMENTATION #include "minIni.h" #if defined NDEBUG #define assert(e) #else #include #endif #if !defined __T #include #include #include /* definition of TCHAR already in minIni.h */ #define __T(s) s #define _tcscat strcat #define _tcschr strchr #define _tcscmp strcmp #define _tcscpy strcpy #define _tcsicmp stricmp #define _tcslen strlen #define _tcsncmp strncmp #define _tcsnicmp strncmp /* DRC needs case sensitive parameters */ #define _tcsrchr strrchr #define _tcstol strtol #define _tcstod strtod #define _totupper toupper #define _stprintf sprintf #define _tfgets fgets #define _tfputs fputs #define _tfopen fopen #define _tremove remove #define _trename rename #endif #if defined __linux || defined __linux__ #define __LINUX__ #endif #if defined FREEBSD && !defined __FreeBSD__ #define __FreeBSD__ #endif #if !defined strnicmp #if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ #define strnicmp strncasecmp #endif #endif #if !defined INI_LINETERM #define INI_LINETERM __T("\n") #endif #if !defined INI_FILETYPE #error Missing definition for INI_FILETYPE. #endif #if !defined sizearray #define sizearray(a) (sizeof(a) / sizeof((a)[0])) #endif enum quote_option { QUOTE_NONE, QUOTE_ENQUOTE, QUOTE_DEQUOTE }; static TCHAR *skipleading(const TCHAR *str) { assert(str != NULL); while (*str != '\0' && *str <= ' ') str++; return (TCHAR *)str; } static TCHAR *skiptrailing(const TCHAR *str, const TCHAR *base) { assert(str != NULL); assert(base != NULL); while (str > base && *(str-1) <= ' ') str--; return (TCHAR *)str; } static TCHAR *striptrailing(TCHAR *str) { TCHAR *ptr = skiptrailing(_tcschr(str, '\0'), str); assert(ptr != NULL); *ptr = '\0'; return str; } static TCHAR *save_strncpy(TCHAR *dest, const TCHAR *source, size_t maxlen, enum quote_option option) { size_t d, s; assert(maxlen>0); assert(dest <= source || dest >= source + maxlen); if (option == QUOTE_ENQUOTE && maxlen < 3) option = QUOTE_NONE; /* cannot store two quotes and a terminating zero in less than 3 characters */ switch (option) { case QUOTE_NONE: for (d = 0; d < maxlen - 1 && source[d] != '\0'; d++) dest[d] = source[d]; assert(d < maxlen); dest[d] = '\0'; break; case QUOTE_ENQUOTE: d = 0; dest[d++] = '"'; for (s = 0; source[s] != '\0' && d < maxlen - 2; s++, d++) { if (source[s] == '"') { if (d >= maxlen - 3) break; /* no space to store the escape character plus the one that follows it */ dest[d++] = '\\'; } /* if */ dest[d] = source[s]; } /* for */ dest[d++] = '"'; dest[d] = '\0'; break; case QUOTE_DEQUOTE: for (d = s = 0; source[s] != '\0' && d < maxlen - 1; s++, d++) { if ((source[s] == '"' || source[s] == '\\') && source[s + 1] == '"') s++; dest[d] = source[s]; } /* for */ dest[d] = '\0'; break; default: assert(0); } /* switch */ return dest; } static TCHAR *cleanstring(TCHAR *string, enum quote_option *quotes) { int isstring; TCHAR *ep; assert(string != NULL); assert(quotes != NULL); /* Remove a trailing comment */ isstring = 0; for (ep = string; *ep != '\0' && ((*ep != ';' && *ep != '#') || isstring); ep++) { if (*ep == '"') { if (*(ep + 1) == '"') ep++; /* skip "" (both quotes) */ else isstring = !isstring; /* single quote, toggle isstring */ } else if (*ep == '\\' && *(ep + 1) == '"') { ep++; /* skip \" (both quotes */ } /* if */ } /* for */ assert(ep != NULL && (*ep == '\0' || *ep == ';' || *ep == '#')); *ep = '\0'; /* terminate at a comment */ striptrailing(string); /* Remove double quotes surrounding a value */ *quotes = QUOTE_NONE; if (*string == '"' && (ep = _tcschr(string, '\0')) != NULL && *(ep - 1) == '"') { string++; *--ep = '\0'; *quotes = QUOTE_DEQUOTE; /* this is a string, so remove escaped characters */ } /* if */ return string; } static int getkeystring(INI_FILETYPE *fp, const TCHAR *Section, const TCHAR *Key, int idxSection, int idxKey, TCHAR *Buffer, int BufferSize) { TCHAR *sp, *ep; int len, idx; enum quote_option quotes; TCHAR LocalBuffer[INI_BUFFERSIZE]; assert(fp != NULL); /* Move through file 1 line at a time until a section is matched or EOF. If * parameter Section is NULL, only look at keys above the first section. If * idxSection is postive, copy the relevant section name. */ len = (Section != NULL) ? _tcslen(Section) : 0; if (len > 0 || idxSection >= 0) { idx = -1; do { if (!ini_read(LocalBuffer, INI_BUFFERSIZE, fp)) return 0; sp = skipleading(LocalBuffer); ep = _tcschr(sp, ']'); } while (*sp != '[' || ep == NULL || (((int)(ep-sp-1) != len || _tcsnicmp(sp+1,Section,len) != 0) && ++idx != idxSection)); if (idxSection >= 0) { if (idx == idxSection) { assert(ep != NULL); assert(*ep == ']'); *ep = '\0'; save_strncpy(Buffer, sp + 1, BufferSize, QUOTE_NONE); return 1; } /* if */ return 0; /* no more section found */ } /* if */ } /* if */ /* Now that the section has been found, find the entry. * Stop searching upon leaving the section's area. */ assert(Key != NULL || idxKey >= 0); len = (Key != NULL) ? (int)_tcslen(Key) : 0; idx = -1; do { if (!ini_read(LocalBuffer,INI_BUFFERSIZE,fp) || *(sp = skipleading(LocalBuffer)) == '[') return 0; sp = skipleading(LocalBuffer); ep = _tcschr(sp, '='); /* Parse out the equal sign */ if (ep == NULL) ep = _tcschr(sp, ':'); } while (*sp == ';' || *sp == '#' || ep == NULL || (((int)(skiptrailing(ep,sp)-sp) != len || _tcsnicmp(sp,Key,len) != 0) && ++idx != idxKey)); if (idxKey >= 0) { if (idx == idxKey) { assert(ep != NULL); assert(*ep == '=' || *ep == ':'); *ep = '\0'; striptrailing(sp); save_strncpy(Buffer, sp, BufferSize, QUOTE_NONE); return 1; } /* if */ return 0; /* no more key found (in this section) */ } /* if */ /* Copy up to BufferSize chars to buffer */ assert(ep != NULL); assert(*ep == '=' || *ep == ':'); sp = skipleading(ep + 1); sp = cleanstring(sp, "es); /* Remove a trailing comment */ save_strncpy(Buffer, sp, BufferSize, quotes); return 1; } /** ini_gets() * \param Section the name of the section to search for * \param Key the name of the entry to find the value of * \param DefValue default string in the event of a failed read * \param Buffer a pointer to the buffer to copy into * \param BufferSize the maximum number of characters to copy * \param Filename the name and full path of the .ini file to read from * * \return the number of characters copied into the supplied buffer */ int ini_gets(const TCHAR *Section, const TCHAR *Key, const TCHAR *DefValue, TCHAR *Buffer, int BufferSize, const TCHAR *Filename) { INI_FILETYPE fp; int ok = 0; if (Buffer == NULL || BufferSize <= 0 || Key == NULL) return 0; if (ini_openread(Filename, &fp)) { ok = getkeystring(&fp, Section, Key, -1, -1, Buffer, BufferSize); (void)ini_close(&fp); } /* if */ if (!ok) save_strncpy(Buffer, DefValue, BufferSize, QUOTE_NONE); return _tcslen(Buffer); } /** ini_getl() * \param Section the name of the section to search for * \param Key the name of the entry to find the value of * \param DefValue the default value in the event of a failed read * \param Filename the name of the .ini file to read from * * \return the value located at Key */ long ini_getl(const TCHAR *Section, const TCHAR *Key, long DefValue, const TCHAR *Filename) { TCHAR LocalBuffer[64]; int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename); return (len == 0) ? DefValue : ((len >= 2 && _totupper(LocalBuffer[1]) == 'X') ? _tcstol(LocalBuffer, NULL, 16) : _tcstol(LocalBuffer, NULL, 10)); } #if defined INI_REAL /** ini_getf() * \param Section the name of the section to search for * \param Key the name of the entry to find the value of * \param DefValue the default value in the event of a failed read * \param Filename the name of the .ini file to read from * * \return the value located at Key */ INI_REAL ini_getf(const TCHAR *Section, const TCHAR *Key, INI_REAL DefValue, const TCHAR *Filename) { TCHAR LocalBuffer[64]; int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename); return (len == 0) ? DefValue : ini_atof(LocalBuffer); } #endif /** ini_getbool() * \param Section the name of the section to search for * \param Key the name of the entry to find the value of * \param DefValue default value in the event of a failed read; it should * zero (0) or one (1). * \param Buffer a pointer to the buffer to copy into * \param BufferSize the maximum number of characters to copy * \param Filename the name and full path of the .ini file to read from * * A true boolean is found if one of the following is matched: * - A string starting with 'y' or 'Y' * - A string starting with 't' or 'T' * - A string starting with '1' * * A false boolean is found if one of the following is matched: * - A string starting with 'n' or 'N' * - A string starting with 'f' or 'F' * - A string starting with '0' * * \return the true/false flag as interpreted at Key */ int ini_getbool(const TCHAR *Section, const TCHAR *Key, int DefValue, const TCHAR *Filename) { TCHAR LocalBuffer[2]; int ret; ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename); LocalBuffer[0] = toupper(LocalBuffer[0]); if (LocalBuffer[0] == 'Y' || LocalBuffer[0] == '1' || LocalBuffer[0] == 'T') ret = 1; else if (LocalBuffer[0] == 'N' || LocalBuffer[0] == '0' || LocalBuffer[0] == 'F') ret = 0; else ret = DefValue; return(ret); } /** ini_getsection() * \param idx the zero-based sequence number of the section to return * \param Buffer a pointer to the buffer to copy into * \param BufferSize the maximum number of characters to copy * \param Filename the name and full path of the .ini file to read from * * \return the number of characters copied into the supplied buffer */ int ini_getsection(int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename) { INI_FILETYPE fp; int ok = 0; if (Buffer == NULL || BufferSize <= 0 || idx < 0) return 0; if (ini_openread(Filename, &fp)) { ok = getkeystring(&fp, NULL, NULL, idx, -1, Buffer, BufferSize); (void)ini_close(&fp); } /* if */ if (!ok) *Buffer = '\0'; return _tcslen(Buffer); } /** ini_getkey() * \param Section the name of the section to browse through, or NULL to * browse through the keys outside any section * \param idx the zero-based sequence number of the key to return * \param Buffer a pointer to the buffer to copy into * \param BufferSize the maximum number of characters to copy * \param Filename the name and full path of the .ini file to read from * * \return the number of characters copied into the supplied buffer */ int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename) { INI_FILETYPE fp; int ok = 0; if (Buffer == NULL || BufferSize <= 0 || idx < 0) return 0; if (ini_openread(Filename, &fp)) { ok = getkeystring(&fp, Section, NULL, -1, idx, Buffer, BufferSize); (void)ini_close(&fp); } /* if */ if (!ok) *Buffer = '\0'; return _tcslen(Buffer); } #if !defined INI_NOBROWSE /** ini_browse() * \param Callback a pointer to a function that will be called for every * setting in the INI file. * \param UserData arbitrary data, which the function passes on the the * \c Callback function * \param Filename the name and full path of the .ini file to read from * * \return 1 on success, 0 on failure (INI file not found) * * \note The \c Callback function must return 1 to continue * browsing through the INI file, or 0 to stop. Even when the * callback stops the browsing, this function will return 1 * (for success). */ int ini_browse(INI_CALLBACK Callback, const void *UserData, const TCHAR *Filename) { TCHAR LocalBuffer[INI_BUFFERSIZE]; TCHAR *sp, *ep; int lenSec, lenKey; enum quote_option quotes; INI_FILETYPE fp; if (Callback == NULL) return 0; if (!ini_openread(Filename, &fp)) return 0; LocalBuffer[0] = '\0'; /* copy an empty section in the buffer */ lenSec = _tcslen(LocalBuffer) + 1; for ( ;; ) { if (!ini_read(LocalBuffer + lenSec, INI_BUFFERSIZE - lenSec, &fp)) break; sp = skipleading(LocalBuffer + lenSec); /* ignore empty strings and comments */ if (*sp == '\0' || *sp == ';' || *sp == '#') continue; /* see whether we reached a new section */ ep = _tcschr(sp, ']'); if (*sp == '[' && ep != NULL) { *ep = '\0'; save_strncpy(LocalBuffer, sp + 1, INI_BUFFERSIZE, QUOTE_NONE); lenSec = _tcslen(LocalBuffer) + 1; continue; } /* if */ /* not a new section, test for a key/value pair */ ep = _tcschr(sp, '='); /* test for the equal sign or colon */ if (ep == NULL) ep = _tcschr(sp, ':'); if (ep == NULL) continue; /* invalid line, ignore */ *ep++ = '\0'; /* split the key from the value */ striptrailing(sp); save_strncpy(LocalBuffer + lenSec, sp, INI_BUFFERSIZE - lenSec, QUOTE_NONE); lenKey = _tcslen(LocalBuffer + lenSec) + 1; /* clean up the value */ sp = skipleading(ep); sp = cleanstring(sp, "es); /* Remove a trailing comment */ save_strncpy(LocalBuffer + lenSec + lenKey, sp, INI_BUFFERSIZE - lenSec - lenKey, quotes); /* call the callback */ if (!Callback(LocalBuffer, LocalBuffer + lenSec, LocalBuffer + lenSec + lenKey, UserData)) break; } /* for */ (void)ini_close(&fp); return 1; } #endif /* INI_NOBROWSE */ #if ! defined INI_READONLY static void ini_tempname(TCHAR *dest, const TCHAR *source, int maxlength) { TCHAR *p; save_strncpy(dest, source, maxlength, QUOTE_NONE); p = _tcsrchr(dest, '\0'); assert(p != NULL); *(p - 1) = '~'; } static enum quote_option check_enquote(const TCHAR *Value) { const TCHAR *p; /* run through the value, if it has trailing spaces, or '"', ';' or '#' * characters, enquote it */ assert(Value != NULL); for (p = Value; *p != '\0' && *p != '"' && *p != ';' && *p != '#'; p++) /* nothing */; return (*p != '\0' || (p > Value && *(p - 1) == ' ')) ? QUOTE_ENQUOTE : QUOTE_NONE; } static void writesection(TCHAR *LocalBuffer, const TCHAR *Section, INI_FILETYPE *fp) { TCHAR *p; if (Section != NULL && _tcslen(Section) > 0) { LocalBuffer[0] = '['; save_strncpy(LocalBuffer + 1, Section, INI_BUFFERSIZE - 4, QUOTE_NONE); /* -1 for '[', -1 for ']', -2 for '\r\n' */ p = _tcsrchr(LocalBuffer, '\0'); assert(p != NULL); *p++ = ']'; _tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */ (void)ini_write(LocalBuffer, fp); } /* if */ } static void writekey(TCHAR *LocalBuffer, const TCHAR *Key, const TCHAR *Value, INI_FILETYPE *fp) { TCHAR *p; enum quote_option option = check_enquote(Value); save_strncpy(LocalBuffer, Key, INI_BUFFERSIZE - 3, QUOTE_NONE); /* -1 for '=', -2 for '\r\n' */ p = _tcsrchr(LocalBuffer, '\0'); assert(p != NULL); *p++ = '='; save_strncpy(p, Value, INI_BUFFERSIZE - (p - LocalBuffer) - 2, option); /* -2 for '\r\n' */ p = _tcsrchr(LocalBuffer, '\0'); assert(p != NULL); _tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */ (void)ini_write(LocalBuffer, fp); } static int cache_accum(const TCHAR *string, int *size, int max) { int len = _tcslen(string); if (*size + len >= max) return 0; *size += len; return 1; } static int cache_flush(TCHAR *buffer, int *size, INI_FILETYPE *rfp, INI_FILETYPE *wfp, INI_FILEPOS *mark) { int pos = 0; (void)ini_seek(rfp, mark); assert(buffer != NULL); buffer[0] = '\0'; assert(size != NULL); while (pos < *size) { (void)ini_read(buffer + pos, INI_BUFFERSIZE - pos, rfp); pos += _tcslen(buffer + pos); assert(pos <= *size); } /* while */ if (buffer[0] != '\0') (void)ini_write(buffer, wfp); (void)ini_tell(rfp, mark); /* update mark */ *size = 0; /* return whether the buffer ended with a line termination */ return (_tcscmp(buffer + pos - _tcslen(INI_LINETERM), INI_LINETERM) == 0); } static int close_rename(INI_FILETYPE *rfp, INI_FILETYPE *wfp, const TCHAR *filename, TCHAR *buffer) { (void)ini_close(rfp); (void)ini_close(wfp); (void)ini_remove(filename); (void)ini_tempname(buffer, filename, INI_BUFFERSIZE); (void)ini_rename(buffer, filename); return 1; } /** ini_puts() * \param Section the name of the section to write the string in * \param Key the name of the entry to write, or NULL to erase all keys in the section * \param Value a pointer to the buffer the string, or NULL to erase the key * \param Filename the name and full path of the .ini file to write to * * \return 1 if successful, otherwise 0 */ int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const TCHAR *Filename) { INI_FILETYPE rfp; INI_FILETYPE wfp; INI_FILEPOS mark; TCHAR *sp, *ep; TCHAR LocalBuffer[INI_BUFFERSIZE]; int len, match, flag, cachelen; assert(Filename != NULL); if (!ini_openread(Filename, &rfp)) { /* If the .ini file doesn't exist, make a new file */ if (Key != NULL && Value != NULL) { if (!ini_openwrite(Filename, &wfp)) return 0; writesection(LocalBuffer, Section, &wfp); writekey(LocalBuffer, Key, Value, &wfp); (void)ini_close(&wfp); } /* if */ return 1; } /* if */ /* If parameters Key and Value are valid (so this is not an "erase" request) * and the setting already exists and it already has the correct value, do * nothing. This early bail-out avoids rewriting the INI file for no reason. */ if (Key != NULL && Value != NULL) { (void)ini_tell(&rfp, &mark); match = getkeystring(&rfp, Section, Key, -1, -1, LocalBuffer, sizearray(LocalBuffer)); if (match && _tcscmp(LocalBuffer,Value) == 0) { (void)ini_close(&rfp); return 1; } /* if */ /* key not found, or different value -> proceed (but rewind the input file first) */ (void)ini_seek(&rfp, &mark); } /* if */ /* Get a temporary file name to copy to. Use the existing name, but with * the last character set to a '~'. */ ini_tempname(LocalBuffer, Filename, INI_BUFFERSIZE); if (!ini_openwrite(LocalBuffer, &wfp)) { (void)ini_close(&rfp); return 0; } /* if */ (void)ini_tell(&rfp, &mark); cachelen = 0; /* Move through the file one line at a time until a section is * matched or until EOF. Copy to temp file as it is read. */ len = (Section != NULL) ? _tcslen(Section) : 0; if (len > 0) { do { if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) { /* Failed to find section, so add one to the end */ flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); if (Key!=NULL && Value!=NULL) { if (!flag) (void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */ writesection(LocalBuffer, Section, &wfp); writekey(LocalBuffer, Key, Value, &wfp); } /* if */ return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */ } /* if */ /* Copy the line from source to dest, but not if this is the section that * we are looking for and this section must be removed */ sp = skipleading(LocalBuffer); ep = _tcschr(sp, ']'); match = (*sp == '[' && ep != NULL && (int)(ep-sp-1) == len && _tcsnicmp(sp + 1,Section,len) == 0); if (!match || Key != NULL) { if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) { cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); } /* if */ } /* if */ } while (!match); } /* if */ cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); /* when deleting a section, the section head that was just found has not been * copied to the output file, but because this line was not "accumulated" in * the cache, the position in the input file was reset to the point just * before the section; this must now be skipped (again) */ if (Key == NULL) { (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); (void)ini_tell(&rfp, &mark); } /* if */ /* Now that the section has been found, find the entry. Stop searching * upon leaving the section's area. Copy the file as it is read * and create an entry if one is not found. */ len = (Key!=NULL) ? _tcslen(Key) : 0; for( ;; ) { if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) { /* EOF without an entry so make one */ flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); if (Key!=NULL && Value!=NULL) { if (!flag) (void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */ writekey(LocalBuffer, Key, Value, &wfp); } /* if */ return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */ } /* if */ sp = skipleading(LocalBuffer); ep = _tcschr(sp, '='); /* Parse out the equal sign */ if (ep == NULL) ep = _tcschr(sp, ':'); match = (ep != NULL && (int)(skiptrailing(ep,sp)-sp) == len && _tcsnicmp(sp,Key,len) == 0); if ((Key != NULL && match) || *sp == '[') break; /* found the key, or found a new section */ /* copy other keys in the section */ if (Key == NULL) { (void)ini_tell(&rfp, &mark); /* we are deleting the entire section, so update the read position */ } else { if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) { cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); } /* if */ } /* if */ } /* for */ /* the key was found, or we just dropped on the next section (meaning that it * wasn't found); in both cases we need to write the key, but in the latter * case, we also need to write the line starting the new section after writing * the key */ flag = (*sp == '['); cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); if (Key != NULL && Value != NULL) writekey(LocalBuffer, Key, Value, &wfp); /* cache_flush() reset the "read pointer" to the start of the line with the * previous key or the new section; read it again (because writekey() destroyed * the buffer) */ (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); if (flag) { /* the new section heading needs to be copied to the output file */ cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); } else { /* forget the old key line */ (void)ini_tell(&rfp, &mark); } /* if */ /* Copy the rest of the INI file */ while (ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) { if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) { cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); (void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp); cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE); } /* if */ } /* while */ cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark); return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */ } /* Ansi C "itoa" based on Kernighan & Ritchie's "Ansi C" book. */ #define ABS(v) ((v) < 0 ? -(v) : (v)) static void strreverse(TCHAR *str) { TCHAR t; int i, j; for (i = 0, j = _tcslen(str) - 1; i < j; i++, j--) { t = str[i]; str[i] = str[j]; str[j] = t; } /* for */ } static void long2str(long value, TCHAR *str) { int i = 0; long sign = value; int n; /* generate digits in reverse order */ do { n = (int)(value % 10); /* get next lowest digit */ str[i++] = (TCHAR)(ABS(n) + '0'); /* handle case of negative digit */ } while (value /= 10); /* delete the lowest digit */ if (sign < 0) str[i++] = '-'; str[i] = '\0'; strreverse(str); } /** ini_putl() * \param Section the name of the section to write the value in * \param Key the name of the entry to write * \param Value the value to write * \param Filename the name and full path of the .ini file to write to * * \return 1 if successful, otherwise 0 */ int ini_putl(const TCHAR *Section, const TCHAR *Key, long Value, const TCHAR *Filename) { TCHAR LocalBuffer[32]; long2str(Value, LocalBuffer); return ini_puts(Section, Key, LocalBuffer, Filename); } #if defined INI_REAL /** ini_putf() * \param Section the name of the section to write the value in * \param Key the name of the entry to write * \param Value the value to write * \param Filename the name and full path of the .ini file to write to * * \return 1 if successful, otherwise 0 */ int ini_putf(const TCHAR *Section, const TCHAR *Key, INI_REAL Value, const TCHAR *Filename) { TCHAR LocalBuffer[64]; ini_ftoa(LocalBuffer, Value); return ini_puts(Section, Key, LocalBuffer, Filename); } #endif /* INI_REAL */ #endif /* !INI_READONLY */ #if defined PORTABLE_STRNICMP int strnicmp(const TCHAR *s1, const TCHAR *s2, size_t n) { register unsigned TCHAR c1, c2; while (n-- != 0 && (*s1 || *s2)) { c1 = *(const unsigned TCHAR *)s1++; if ('a' <= c1 && c1 <= 'z') c1 += ('A' - 'a'); c2 = *(const unsigned TCHAR *)s2++; if ('a' <= c2 && c2 <= 'z') c2 += ('A' - 'a'); if (c1 != c2) return c1 - c2; } /* while */ return 0; } #endif /* PORTABLE_STRNICMP */ drc-3.2.2/source/minIni/minGlue.h0000644000076400001450000000416011707310610015542 0ustar denisitadm/* Glue functions for the minIni library, based on the C/C++ stdio library * * Or better said: this file contains macros that maps the function interface * used by minIni to the standard C/C++ file I/O functions. * * Copyright (c) CompuPhase, 2008-2012 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ /* Changed to remove float support, use read only ini files and ansi only charset. */ /* map required file I/O types and functions to the standard C library */ #include #define INI_FILETYPE FILE* #define ini_openread(filename,file) ((*(file) = fopen((filename),"r")) != NULL) #define ini_openwrite(filename,file) ((*(file) = fopen((filename),"w")) != NULL) #define ini_close(file) (fclose(*(file)) == 0) #define ini_read(buffer,size,file) (fgets((buffer),(size),*(file)) != NULL) #define ini_write(buffer,file) (fputs((buffer),*(file)) >= 0) #define ini_rename(source,dest) (rename((source), (dest)) == 0) #define ini_remove(filename) (remove(filename) == 0) #define INI_FILEPOS fpos_t #define ini_tell(file,pos) (fgetpos(*(file), (pos)) == 0) #define ini_seek(file,pos) (fsetpos(*(file), (pos)) == 0) /* for floating-point support, define additional types and functions */ /* No need for floating point in DRC */ /* #define INI_REAL float #define ini_ftoa(string,value) sprintf((string),"%f",(value)) #define ini_atof(string) (INI_REAL)strtod((string),NULL) */ /* DRC Additions */ #define INI_READONLY #define INI_ANSIONLY drc-3.2.2/source/drc.h0000644000076400001450000001005513163136777013511 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2017 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@neomerica.it This program uses 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. ****************************************************************************/ /* Header generale DRC */ #ifndef DRC_h #define DRC_h #include "cfgparse.h" #include /* Decommentare per abilitare la compilazione in doppia precisione */ /* Uncomment to enable double precision computation */ #define UseDouble /* Commentare per disabilitare l'uso delle routine FFT incluse nella GSL */ /* Comment out to disable GSL FFT routines */ #define UseGSLFft /* Decommentare per abilitare l'uso delle routine FFT di Ooura per potenze di 2 */ /* Le routine FFT di Ooura sono leggermente meno accurate delle routine GSL ma sono anche pi veloci */ /* Uncomment to enable the use of the Ooura FFT routines for power of 2 lenghts */ /* The Ooura FFT routines are a little less accurate then the GSL FFT routines but are also noticeably faster */ /* #define UseOouraFft */ #ifdef UseDouble /* Tipo floating point usato per le elaborazioni */ #define DRCFloat double /* Tipo corrispondente per l'importazione di valori di configurazione */ #define DRCCfgFloat CfgDouble /* Valore minimo e massimo del tipo float in uso */ #ifdef DBL_MIN #define DRCMinFloat DBL_MIN #else #define DRCMinFloat 2.2250738585072014e-308 #endif #ifdef DBL_MAX #define DRCMaxFloat DBL_MAX #else #define DRCMaxFloat 1.7976931348623158e+308 #endif #ifdef DBL_EPSILON #define DRCEpsFloat DBL_EPSILON #else #define DRCEpsFloat 2.2204460492503131e-016 #endif #else /* Tipo floating point usato per le elaborazioni */ #define DRCFloat float /* Tipo corrispondente per l'importazione di valori di configurazione */ #define DRCCfgFloat CfgFloat /* Valore minimo e massimo del tipo float in uso */ #ifdef FLT_MIN #define DRCMinFloat FLT_MIN #else #define DRCMinFloat 1.175494351e-38F #endif #ifdef FLT_MAX #define DRCMaxFloat FLT_MAX #else #define DRCMaxFloat 3.402823466e+38F #endif #ifdef FLT_EPSILON #define DRCEpsFloat FLT_EPSILON #else #define DRCEpsFloat 1.192092896e-07F #endif #endif /* Tipo floating point usato per l'importazione e l'esportazione dei segnali floating point in doppia precisione */ #define DRCFileDouble double /* Tipo floating point usato per l'importazione e l'esportazione dei segnali floating point in singola precisione */ #define DRCFileFloat float /* Tipo intero usato per l'importazione e l'esportazione dei segnali interi */ #define DRCFileInt short int /* Imposta l'uso delle funzioni trigonometriche ridotte */ #define UseTypedTrigs /* Verifica l'uso delle funzioni trigonometriche ridotte */ #ifdef UseTypedTrigs #ifdef UseDouble #define DRCSin sin #define DRCCos cos #define DRCTan tan #define DRCATan atan #else #define DRCSin sinf #define DRCCos cosf #define DRCTan tanf #define DRCATan atanf #endif #else #define DRCSin sin #define DRCCos cos #define DRCTan tan #define DRCATan atan #endif #endif drc-3.2.2/source/dspwind.cpp0000644000076400001450000001150613162156311014727 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : DSPWind.cpp Autore : Sbragion Denis Descrizione : Funzioni per vari tipi di finestratura. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #include "dspwind.h" #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif void HammingWindow(DLReal * A,unsigned int Size) { unsigned int I,Half = Size/2; DLReal C; for(I = 0;I < Half;I++) { C = (DLReal) (0.54-0.46*DLCos(2*M_PI*I/(Size-1))); A[I] *= C; A[Size-I-1] *= C; } } void HanningWindow(DLReal * A,unsigned int Size) { unsigned int I,Half = Size/2; DLReal C; for(I = 0;I < Half;I++) { C = (DLReal) (0.5*(1-DLCos(2*M_PI*I/(Size-1)))); A[I] *= C; A[Size-I-1] *= C; } } void BlackmanWindow(DLReal * A,unsigned int Size) { unsigned int I,J; unsigned int Half = Size/2; DLReal C; DLReal C1 = (DLReal) (2*M_PI/(Size-1)); DLReal C2 = (DLReal) (4*M_PI/(Size-1)); for(I = 0,J = Size - 1;I < Half;I++,J--) { C = (DLReal) (((DLReal) 0.42)-((DLReal) 0.5)*DLCos(C1*I)+((DLReal) 0.08)*DLCos(C2*I)); A[I] *= C; A[J] *= C; } } void SpacedBlackmanWindow(DLReal * A,unsigned int Size, unsigned int Space, WindowType WType) { unsigned int ESize = Size - Space; unsigned int I,Half = (ESize) / 2; DLReal C; DLReal C1 = 2*M_PI/(ESize-1); DLReal C2 = 4*M_PI/(ESize-1); switch (WType) { case WRight: for(I = 0;I < Half;I++) { C = (DLReal) (0.42-0.5*DLCos(C1*I)+0.08*DLCos(C2*I)); A[Size-I-1] *= C; } break; case WFull: for(I = 0;I < Half;I++) { C = (DLReal) (0.42-0.5*DLCos(C1*I)+0.08*DLCos(C2*I)); A[I] *= C; A[Size-I-1] *= C; } break; case WLeft: for(I = 0;I < Half;I++) { C = (DLReal) (0.42-0.5*DLCos(C1*I)+0.08*DLCos(C2*I)); A[I] *= C; } break; } } void HalfBlackmanWindow(DLReal * A,unsigned int Size, unsigned int Space, WindowType WType) { unsigned int ESize = Size - Space; unsigned int I; DLReal C; DLReal C1 = M_PI/(ESize-1); DLReal C2 = 2*M_PI/(ESize-1); switch (WType) { case WRight: for(I = 0;I < ESize;I++) { C = (DLReal) (0.42-0.5*DLCos(C1*I)+0.08*DLCos(C2*I)); A[Size-I-1] *= C; } break; case WFull: perror("dspwind.cpp.HalfBlackmanWindow: WFull not supported"); break; case WLeft: for(I = 0;I < ESize;I++) { C = (DLReal) (0.42-0.5*DLCos(C1*I)+0.08*DLCos(C2*I)); A[I] *= C; } break; } } void BartlettWindow(DLReal * A,unsigned int Size) { unsigned int I,Half = Size/2; DLReal C,R = ((DLReal) Size-1)/2; for(I = 0;I < Half;I++) { C = I/R; A[I] *= C; A[Size-I-1] *= C; } } void BlackmanHarrisWindow(DLReal * A,unsigned int Size) { unsigned int I,Half = Size/2; DLReal C; for(I = 0;I < Half;I++) { C = (DLReal) (0.35875-0.48829*DLCos(2*M_PI*I/(Size-1))+0.14128*DLCos(4*M_PI*I/(Size-1))+0.01168*DLCos(6*M_PI*I/(Size-1))); A[I] *= C; A[Size-I-1] *= C; } } void ExponentialWindow(DLReal * A,unsigned int Size,DLReal P) { unsigned int I,Half = Size/2; DLReal C,X; P = (DLReal) (sqrt(P)); for(I = 0;I < Half;I++) { X = (P*(Half-I))/Half; C = (DLReal) (exp(-X*X)); A[I] *= C; A[Size-I-1] *= C; } } void Ones(DLReal * A,unsigned int Size) { unsigned int I; for(I = 0;I < Size;I++) A[I] = 1; } /***************************************************************************/ drc-3.2.2/source/cfgparse.h0000644000076400001450000000376413162156312014526 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Configuration file parsing utilities */ #ifndef CfgParse_h #define CfgParse_h /* Configuration file type */ typedef enum { CfgSimple, CfgSections } CfgFileType; /* Recognized configuration value types */ typedef enum { CfgEnd, CfgBoolean, CfgString, CfgInt, CfgUInt, CfgLong, CfgULong, CfgFloat, CfgDouble } CfgValueType; /* Structure for parameters definition */ typedef struct { char * PName; CfgValueType PType; void * PValue; } CfgParameter; #ifdef __cplusplus extern "C" { #endif /* Configuration parsing, return the number of parameters read or a negative value on error. */ int CfgParse(const char * CfgFile,CfgParameter * CfgParameters,const CfgFileType FType); /* Free the memory allocated by CfgParse */ void CfgFree(const CfgParameter * CfgParameters); /* Get the last error descrition */ const char * CfgGetLastErrorDsc(void); #ifdef __cplusplus } #endif #endif drc-3.2.2/source/doc/0000755000076400001450000000000013165107356013325 5ustar denisitadmdrc-3.2.2/source/doc/octave/0000755000076400001450000000000013165107357014607 5ustar denisitadmdrc-3.2.2/source/doc/octave/idownsample.m0000644000076400001450000000247311320622700017276 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: ds = idownsample(is, df, flen, fcut, att) ## ## Downsample is by df times (integer) with a filter ## flen taps long, fcut normalized cutoff frequency ## and att dB of stopband attenuation. If att is negative ## a Blackman window is used. function ds = idownsample(is, df, flen, fcut, att) df = floor(df); if (att < 0) ds = fftconv(is, lowpassfir(flen,fcut/df)' .* blackman(flen)); else ds = fftconv(is, lowpassfir(flen,fcut/df)' .* chebwin(flen,att)); endif ds = ds(floor(df/2):df:length(ds)); endfunctiondrc-3.2.2/source/doc/octave/xosim.m0000644000076400001450000000440312260557557016133 0ustar denisitadm## Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: ir = xosim(fs,lpir,lpl,lpd,lpf,lpn,lpt,lpo,hpir,hpl,hpd,hpf,hpn,hpt,hpo) ## ## Makes an xover simulation on two input impulse responses, ## returns the resulting combined impulse response. ## ## fs: sample rate ## lpir: lowpass impulse response ## lpl: lowpass level ## lpd: lowpass delay ## lpf: lowpass xover frequency ## lpn: lowpass xover filter length ## lpt: lowpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## lpo: lowpass xover half order, 0 use a linear phase brickwall, ## negative use a minimum phase brickwall. ## hpir: highpass impulse response ## hpl: highpass level ## hpd: highpass delay ## hpf: highpass xover frequency ## hpn: highpass xover filter length ## hpt: highpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## hpo: highpass xover half order, 0 use a linear phase brickwall, ## negative use a minimum phase brickwall. ## ## Example: ## ## ir = lrxosim(44100,ls,1,0,80,4096,0,0,lm,1,0,80,4096,0,0); ## function ir = xosim(fs,lpir,lpl,lpd,lpf,lpn,lpt,lpo,hpir,hpl,hpd,hpf,hpn,hpt,hpo) # Computes the xover filters [ lpfir, hpfir ] = mkxo(fs,lpl,lpd,lpf,lpn,lpt,lpo,hpl,hpd,hpf,hpn,hpt,hpo); # Force the same filter length lpfir = postpad(lpfir,max(length(lpfir),length(hpfir))); hpfir = postpad(hpfir,max(length(lpfir),length(hpfir))); # Computes the xover impulse response ir = postpad(fftconv(lpfir,lpir) + fftconv(hpfir,hpir),length(lpir)); endfunctiondrc-3.2.2/source/doc/octave/ub3splinev.m0000644000076400001450000000223611320622700017043 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: Y = ub3splinev(XN,YN,X) ## ## Computes the value of the uniform cubic B spline ## defined by XN and YN on the points of the vector X ## This is really slow because it simply evaluates the ## spline function on all X points function Y = ub3splinev(XN,YN,X) N = length(X); Y = zeros(1,N); for I = 1:N Y(I) = ub3splinex(XN,YN,X(I)); endfor endfunctiondrc-3.2.2/source/doc/octave/wsmooth.m0000644000076400001450000000357111320622700016454 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: [mag, freq] = wsmooth(ir,wl,ws); ## ## wsmooth - Smoothing by impulse response warping ## ## ir = input impulse response ## wl = lambda used for warping, usually defined by barkwarp(fs) or erbwarp(fs) ## with fs = sample rate of ir ## ws = smoothing window size, bigger values means less smoothing, typical value is 64 ## ws must be less than floor(length(ir)/2) ## ## [mag, freq] = magnitude response in the frequency points defined by freq ## length(mag) = length(freq) = floor(length(ir)/2) ## freq is the normalized frequency between 0 and 1 function [mag, freq] = wsmooth(ir,wl,ws) # Computes the warped impulse response autocorrelation wir = fft(irwarp(ir,wl,length(ir))); wir = real(ifft(wir .* conj(wir))); # Computes the window wind = blackman(2 * ws); wind = [(wind((ws+1):(2*ws)))' zeros(1,length(wir) - (2*ws)) (wind(1:ws))']; # Windows the warped autocorrelation wir = wir .* wind; # Computes the frequency points freq = wfreq(wl,floor(length(ir)/2)); # Computes the magnitude mag = fft(wir); mag = sqrt(abs(mag(1:floor(length(ir))/2))); endfunction drc-3.2.2/source/doc/octave/mkpatarget.m0000644000076400001450000000270011320622700017104 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## Usage: mkpatarget(s,fs,bw,pds,ppk,sf,ef,np,fname) function mkpatarget(s,fs,bw,pds,ppk,sf,ef,np,fname) # Computes the envelope tev = ssev(s,fs,bw,pds,ppk); # Get the target frequency points tfp = logspace(log10(sf),log10(ef),np); # Interpolates the envenlope at the target frequencies tfm = interp1(linspace(0,fs/2,length(tev)),tev,tfp,'pchip'); # Invert and escales the envelope to 0 db at the lower end tfm = tfm(1) ./ tfm; # Creates the target array ta = zeros(1,2 * np); ta(1:2:(2 * np)) = tfp; ta(2:2:(2 * np)) = 20 * log10(tfm(:)); # Save the target tf = fopen(fname,"wt"); fprintf(tf,"%f %f\n",ta); fclose(tf); endfunctiondrc-3.2.2/source/doc/octave/mrwsmooth.m0000644000076400001450000000547011320622700017013 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: [mag, freq] = mrwsmooth(ir,wl,ws,fj); ## ## mrwsmooth - Multirate smoothing by impulse response warping ## ## ir = input impulse response ## wll,wlh = lambda used for multirate warping, usually defined by barkwarp(fs) or erbwarp(fs) ## with fs = sample rate of ir for wlh, and by barkwarp(fs/df) or erbwarp(fs/df) for wll ## ws = smoothing window size, bigger values means less smoothing, typical value is 64 ## ws must be less than floor(length(ir/ds)/2) ## df = downsampling factor ## fj = normalized join frequency for the multirate filter, usually 0.5 ## fl, att = filter length and stop band attenuation for the downsampling and the multirate filters ## ## [mag, freq] = magnitude response in the frequency points defined by freq ## length(mag) = length(freq) = floor(length(ir)/2) ## freq is the normalized frequency between 0 and 1 function [mag, freq] = mrwsmooth(ir,wl,ws,wm,fj,fl,att); # Makes the filter length odd fl = 1 + 2 * floor(fl/2); # Computes the warped impulse response wir = irwarp(ir,wl,length(ir))'; wind = chebwin(fl,att)'; wiru = fftconv(wir,highpassfir(fl,fj) .* wind); wird = fftconv(wir,lowpassfir(fl,fj) .* wind); # Computes the warped impulse response autocorrelation wiru = fft(wiru); wiru = real(ifft(wiru .* conj(wiru))); # Computes the window wsu = ws; wind = blackman(2*wsu); wind = [(wind((wsu+1):(2*wsu)))' zeros(1,length(wiru) - (2*wsu)) (wind(1:wsu))']'; # Windows the warped autocorrelation wiru = wiru' .* wind; # Computes the downsampled warped impulse response autocorrelation wird = fft(wird); wird = real(ifft(wird .* conj(wird))); # Computes the window wsd = wm*ws; wind = blackman(2*wsd); wind = [(wind((wsd+1):(2*wsd)))' zeros(1,length(wird) - (2*wsd)) (wind(1:wsd))']'; # Windows the warped autocorrelation wird = wird' .* wind; # Computes the magnitude mag = fft(wiru + wird); mag = sqrt(abs(mag(1:floor(length(wiru)/2)))); # Computes the frequency points falu = floor(length(wiru)/2); freq = -angle(freqz([wl 1],[1 wl],falu))/pi; endfunction drc-3.2.2/source/doc/octave/blresample.m0000644000076400001450000000256611320622700017105 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: rs = blresample(is, rf, flen, fcut, att) ## ## Resample is by rf times with a filter ## flen taps long, fcut normalized cutoff frequency ## and att dB of stopband attenuation function rs = blresample(is, rf, flen, fcut, att) # Check if it is a downsampling or an upsampling if rf < 1.0 rs = fftconv(is, lowpassfir(flen,rf * fcut)' .* chebwin(flen,att)); else rs = fftconv(is, lowpassfir(flen,fcut)' .* chebwin(flen,att)); endif os = ceil(length(rs) * rf); rs = blinterpolate((0:(length(rs) - 1)),rs,linspace(0,length(rs) * os / (length(rs) * rf),os)); endfunctiondrc-3.2.2/source/doc/octave/hdmp.m0000644000076400001450000000217312260552444015714 0ustar denisitadm## Copyright (C) 2005-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: m = hdmp(s) ## ## Compute the minimum phase reconstruction of the ## signal s by homomorphic deconvolution. ## function m = hdmp(s) m = abs(fft(s)); m = ifft(log(m .* (m > 0) + realmin() .* (m <= 0))); l = floor(rows(m) / 2) + 1; m(2:l,:) *= 2; m((l + 1):rows(m),:) = 0; m = real(ifft(exp(fft(m)))); endfunctiondrc-3.2.2/source/doc/octave/wfreq.m0000644000076400001450000000242711320622700016077 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: freq = wfreq(wl,n); ## ## wfreq - Return the normalized frequency mapping for the warping factor wl ## ## wl = lambda used for warping, usually defined by barkwarp(fs) or erbwarp(fs) ## with fs = sample rate of ir ## n = number of frequency points ## ## freq is the normalized frequency between 0 and 1 function freq = wfreq(wl,n) # Computes the frequency points freq = linspace(0,pi,n); freq = (freq + 2 * atan((-wl * sin(freq))./(1 + wl * cos(freq))))/pi; endfunction drc-3.2.2/source/doc/octave/blinterpolate.m0000644000076400001450000000230211320622700017607 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: bls = blinterpolate(x, y, xi) ## ## Perform the band limited interpolation of ## function y=f(x) at the points xi. f(x) is assumed ## equal to 0 outside of the values of x. function bls = blinterpolate(x, y, xi) # Transpose the vectors appropriately x = x(:); y = y(:); xi = xi(:); # Computes the interpolation bls = sinc(xi(:,ones(size(x))) - x(:,ones(size(xi)))') * y; endfunctiondrc-3.2.2/source/doc/octave/ssev.m0000644000076400001450000001137111320622700015731 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: sev = ssev(s,fs,bw,pds,ppk) ## ## Computes the smoothed spectral envelope of signal s on a logarithmic ## frequency scale with bw bandwidth resolution and pds peak ## detection strength. If a fourth 'prepeak' argument is supplied ## a further explicit envelope detection step is applied before ## the standard computation. ## ## s = input signal. ## fs = input signal sample rate, needed only if Bark or ERB scaling ## is used. ## bw = bandwidth resolution as a faction of octave, for example 0.25 ## means 1/4 of octave resolution. A value of -1 means Bark scaling ## resolution, a value of -2 means ERB scaling resolution. ## pds = peak detection strength, values above 50 migth lead to ## overflow. When set to values less than or equal to 1, and ## without any prepeak detection enabled, the algorithm provides ## the usual smoothing, either with fractional octave or Bark/ERB. ## resolution. If any prepeak detection is enabled the smoothing ## is applied to the prepeak envelope. ## ppk = optional prepeak processing, must be set to 'prepeak'. ## ## sev = output smoothed spectral envelope, same length of s. ## ## Typical values for psychoacoustic evaluation of the perceived ## frequency response: ## ## sev = ssev(s,fs,-2,15); ## function sev = ssev(s,fs,bw,pds,ppk) # Get the number of signal samples n = length(s); # Allocates the envelope array sev = zeros(1,n); # Check the type of resolution to use if (bw >= 0) # Computes the half bandwidth hbw = (2 ^ (bw / 2)); # Computes the lower and upper bounds index bl = 1 + round((0:(n - 1)) / hbw); bu = 2 + round((0:(n - 1)) * hbw); # Limit the upper bound to the signal length bu = min(n + 1,bu); else if (bw >= -1) # Computes the Bark scaling bl = linspace(fs / (2 * (n - 1)),fs / 2,n - 1); sev(2:n) = barkbwidth(bl); sev(2:n) = (sqrt(sev(2:n) .^ 2 + 4 * bl .^ 2) + sev(2:n)) ./ (2 * bl); sev(1) = sev(2); # Computes the lower and upper bounds index bl = 1 + round((0:(n - 1)) ./ sev); bu = 2 + round((0:(n - 1)) .* sev); # Limit the upper bound to the signal length bu = min(n + 1,bu); else # Computes the ERB scaling bl = linspace(fs / (2 * (n - 1)),fs / 2,n - 1); sev(2:n) = erbbwidth(bl); sev(2:n) = (sqrt(sev(2:n) .^ 2 + 4 * bl .^ 2) + sev(2:n)) ./ (2 * bl); sev(1) = sev(2); # Computes the lower and upper bounds index bl = 1 + round((0:(n - 1)) ./ sev); bu = 2 + round((0:(n - 1)) .* sev); # Limit the upper bound to the signal length bu = min(n + 1,bu); endif endif # Computes the signal spectrum sev = abs(fft(postpad(s(:)',2 * n))(1:n)); # Performs the signal spectrum preconditioning sevmax = max(sev); sev = sev / sevmax; # Check if prepeak detection is enabled if (nargin == 5 && strcmp(ppk,'prepeak') == 1) # Perform the peak detection pp = [1 (find(diff(sign(diff(sev))) == -2) + 1)]; if (pp(length(pp)) != n) pp = [ pp n ]; endif # Interpolates to the original positions sev = interp1(pp,sev(pp),1:n,'pchip'); endif # Check if peak detection is enabled if (pds <= 1) # No peak detection, creates the standard fractional octave # smoothing cumulative sum with appropriate padding sev = cumsum([0 sev]); # Perform the standard fractional octave smoothing sev = (sev(bu) - sev(bl)) ./ (bu - bl); else # Creates the peak smoothing cumulative sum # with appropriate padding sev = cumsum([0 sev] .^ pds); # Perform the peak enhanced smoothing sev = ((sev(bu) - sev(bl)) ./ (bu - bl)) .^ (1 / pds); # Creates the peak smoothing cumulative sum # with appropriate padding sev = cumsum([0 sev]); # Smooth the peak function sev = (sev(bu) - sev(bl)) ./ (bu - bl); endif # Creates the final smoothing cumulative sum # with appropriate padding sev = cumsum([0 sev]); # Performs the final spectrum smoothing and rescaling sev = sevmax * (sev(bu) - sev(bl)) ./ (bu - bl); endfunctiondrc-3.2.2/source/doc/octave/lfxosim.m0000644000076400001450000000435411320622700016435 0ustar denisitadm## Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: ir = lfxosim(fs,lpir,lpl,lpd,lpf,lpn,lpt,hpir,hpl,hpd,hpf,hpn,hpt) ## ## Makes linear phase xover simulation on two input impulse responses, ## returns the resulting combined impulse response. ## ## fs: sample rate ## lpir: lowpass impulse response ## lpl: lowpass level ## lpd: lowpass delay ## lpf: lowpass xover frequency ## lpn: lowpass xover filter length ## lpt: lowpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## hpir: highpass impulse response ## hpl: highpass level ## hpd: highpass delay ## hpf: highpass xover frequency ## lpn: highpass xover filter length ## hpt: highpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## ## Example: ## ## ir = lrxosim(44100,ls,1,0,80,4096,0,lm,1,0,80,4096,0); ## function ir = lfxosim(fs,lpir,lpl,lpd,lpf,lpn,lpt,hpir,hpl,hpd,hpf,hpn,hpt) # Computes the low pass filter if (lpt == 0) lpfir = lpl * prepad(bandpassfir(lpn - lpd,0,2 * lpf / fs) .* blackman(lpn - lpd)',lpn); else lpfir = lpl * prepad(bandpassfir(lpn - lpd,0,2 * lpf / fs) .* chebwin(lpn - lpd,lpt)',lpn); endif # Computes the high pass filter if (hpt == 0) hpfir = hpl * prepad(bandpassfir(hpn - hpd,2 * hpf / fs,1) .* blackman(hpn - hpd)',hpn); else hpfir = hpl * prepad(bandpassfir(hpn - hpd,2 * hpf / fs,1) .* chebwin(hpn - hpd,hpt)',hpn); endif # Computes the xover impulse response ir = fftconv(lpfir,lpir) + fftconv(hpfir,hpir); endfunctiondrc-3.2.2/source/doc/octave/fslprefilt.m0000644000076400001450000000264511320622700017127 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: f = fslprefilt(sf, sw, ef, ew, we, np) ## ## Compute the exponential based prefiltering ## cutoff frequencies ## ## sf = start frequency ## sw = start window ## ef = end frequency ## ew = end window ## we = window exponent ## np = number of points function f = fslprefilt(sf, sw, ef, ew, we, np) if (nargin != 6) usage("f = fslprefilt(sf, sw, ef, ew, we, np)"); endif # Computes the prefiltering coefficients B = exp(log(sf / ef) / we); Q = ((B * sw) - ew) / (1.0 - B); A = 1.0 / (ef * ((ew + Q) ^ we)); # Computes the filter cut frequency f = 1.0 ./ (A * ((linspace(ew,sw,np) .+ Q) .^ we)); endfunctiondrc-3.2.2/source/doc/octave/cplxsmooth.m0000644000076400001450000001035611320622700017153 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: sev = cplxsmooth(s,fs,bw,pds) ## ## Computes the smoothed complex spectral envelope of signal s on a ## logarithmic frequency scale with bw bandwidth resolution and pds peak ## detection strength. The signal s must be centers with respect to the ## 0 of the axis time. ## ## s = input signal. ## fs = input signal sample rate, needed only if Bark or ERB scaling ## is used. ## bw = bandwidth resolution as a faction of octave, for example 0.25 ## means 1/4 of octave resolution. A value of -1 means Bark scaling ## resolution, a value of -2 means ERB scaling resolution. ## pds = peak detection strength, values above 50 migth lead to ## overflow. When set to values less than or equal to 1, and ## without any prepeak detection enabled, the algorithm provides ## the usual smoothing, either with fractional octave or Bark/ERB. ## resolution. If any prepeak detection is enabled the smoothing ## is applied to the prepeak envelope. ## ## sev = output smoothed complex spectral envelope, same length of s. ## ## Typical values for psychoacoustic evaluation of the perceived ## frequency response: ## ## sev = cplxsmooth(s,fs,-2,15); ## function sev = cplxsmooth(s,fs,bw,pds,ppk) # Get the number of signal samples n = length(s); # Allocates the envelope array sev = zeros(1,n); # Check the type of resolution to use if (bw >= 0) # Computes the half bandwidth hbw = (2 ^ (bw / 2)); # Computes the lower and upper bounds index bl = 1 + round((0:(n - 1)) / hbw); bu = 2 + round((0:(n - 1)) * hbw); # Limit the upper bound to the signal length bu = min(n + 1,bu); else if (bw >= -1) # Computes the Bark scaling bl = linspace(fs / (2 * (n - 1)),fs / 2,n - 1); sev(2:n) = barkbwidth(bl); sev(2:n) = (sqrt(sev(2:n) .^ 2 + 4 * bl .^ 2) + sev(2:n)) ./ (2 * bl); sev(1) = sev(2); # Computes the lower and upper bounds index bl = 1 + round((0:(n - 1)) ./ sev); bu = 2 + round((0:(n - 1)) .* sev); # Limit the upper bound to the signal length bu = min(n + 1,bu); else # Computes the ERB scaling bl = linspace(fs / (2 * (n - 1)),fs / 2,n - 1); sev(2:n) = erbbwidth(bl); sev(2:n) = (sqrt(sev(2:n) .^ 2 + 4 * bl .^ 2) + sev(2:n)) ./ (2 * bl); sev(1) = sev(2); # Computes the lower and upper bounds index bl = 1 + round((0:(n - 1)) ./ sev); bu = 2 + round((0:(n - 1)) .* sev); # Limit the upper bound to the signal length bu = min(n + 1,bu); endif endif # Computes the signal spectrum sev = fft(postpad(s(:)',2 * n))(1:n); # Check if peak detection is enabled if (pds <= 1) # No peak detection, creates the standard fractional octave # smoothing cumulative sum with appropriate padding sev = cumsum([0 sev]); # Perform the standard fractional octave smoothing sev = ((sev(bu) - sev(bl)) ./ (bu - bl)); else # Creates the peak smoothing cumulative sum # with appropriate padding sev = cumsum([0 sev] .^ pds); # Perform the peak enhanced smoothing sev = ((sev(bu) - sev(bl)) ./ (bu - bl)) .^ (1 / pds); # Creates the peak smoothing cumulative sum # with appropriate padding sev = cumsum([0 sev]); # Smooth the peak function sev = (sev(bu) - sev(bl)) ./ (bu - bl); endif # Creates the final smoothing cumulative sum # with appropriate padding sev = cumsum([0 sev]); # Performs the final spectrum smoothing and rescaling sev = (sev(bu) - sev(bl)) ./ (bu - bl); endfunctiondrc-3.2.2/source/doc/octave/bandpassfir.m0000644000076400001450000000253011320622700017242 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: f = bandpassfir(n,lc,hc) ## ## Compute an unwindowed bandpass FIR filter ## ## n = filter len ## lc = normalized low cutoff frequency ## hc = normalized high cutoff frequency function f = bandpassfir(n,lc,hc) ho = fix(n/2); d = pi * (hc - lc) / 2; s = pi * (hc + lc) / 2; if (ho == n/2) f = (2 / pi) * sin(d * ((1:ho) - 0.5)) .* cos(s * ((1:ho) - 0.5)) ./ ((1:ho) - 0.5); f = [ f(ho:-1:1) f]; else f = (2 / pi) * sin(d * (1:ho)) .* cos(s * (1:ho)) ./ (1:ho); f = [ f(ho:-1:1) (hc - lc) f ]; endif endfunctiondrc-3.2.2/source/doc/octave/irslprefilt.m0000644000076400001450000000703611320622700017313 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: pir = irslprefilt(ir,ic,sf,sw,ef,ew,we,fl,fs,wg,pg) ## ## Perform a sliding lowpass prefiltering on the right side of the time-frequency plane ## ## ir = impulse response ## ic = impulse center ## sf = normalized start frequency ## sw = start window ## ef = normalized end frequency ## ew = end window ## we = window exponent ## fl = filter len ## fs = filter sharpness ## wg = window gap ## pg = pre impulse center gap ## ## The output signal length is increased by floor((1 + 2 * floor((fl-1)/2))/2) ## so the final output length is given by: ## ## pg + sw + floor((1 + 2 * floor((fl-1)/2))/2) ## ## The input impulse response is left untouched up to sample pg + ew -1 function pir = irslprefilt(ir,ic,sf,sw,ef,ew,we,fl,fs,wg,pg) # Computes the effective filter len efl = 1 + 2 * floor((fl-1)/2); # Extract the impulse response to be filtered ir = ir(:); if ((length(ir) - ic) < sw) wir = [ ir(ic:length(ir)) zeros(1,sw - (lenght(ir) - ic)) ]; else wir = ir(ic:(ic + sw - 1)); endif # Prepare the initial window esw = sw - wg; wind = blackman(2 * esw); wind = [ ones(1,wg) wind((esw + 1):(2 * esw))' ]'; # Apply the initial window wir = wir .* wind; # Pad the input ir wir = [ wir' zeros(1,efl) ]; # Computes the half filter length hfl = floor(efl/2); # Creates the output ir pir = zeros(1,sw + hfl); # Creates the base filter window wind = blackman(efl); # Computes the base filter wfir = lowpassfir(efl,sf) .* wind'; # Set the initial parameters cfl = efl; chfl = hfl; # Initial lowpass convolution loop for wp = sw+hfl:-1:sw-1 # Check if the window limit has been reached cws = floor(fs * wp); if (chfl > cws) # Recomputes the filter lengths chfl = cws; cfl = 1 + (chfl * 2); # Creates the window wind = blackman(cfl); # Creates the filter wfir = lowpassfir(cfl,sf) .* wind'; endif # Output the filtered sample pir(wp) = wir((1+wp-chfl):(1+wp+chfl)) * wfir'; endfor ## Computes the prefiltering coefficients B = exp(log(sf / ef) / we); Q = ((B * sw) - ew) / (1.0 - B); A = 1.0 / (ef * ((ew + Q) ^ we)); # Set the initial parameters cfl = efl; chfl = hfl; # Main convolution loop for wp = sw:-1:ew # Computes the filter cut frequency fc = 1.0 / (A * ((wp + Q) ^ we)); # Check if the window limit has been reached cws = floor(fs * wp); if (chfl > cws) # Recomputes the filter lengths chfl = cws; cfl = 1 + (chfl * 2); # Creates the window wind = blackman(cfl); endif # Creates the filter wfir = lowpassfir(cfl,fc) .* wind'; # Output the filtered sample pir(wp) = wir((1+wp-chfl):(1+wp+chfl)) * wfir'; endfor # Add the initial part of the ir pir = [ ir((ic-pg):(ic+ew-1))' pir(ew:(sw+hfl)) ]; endfunctiondrc-3.2.2/source/doc/octave/wslprefilt.m0000644000076400001450000000263711320622700017151 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: w = wslprefilt(sf, sw, ef, ew, we, np) ## ## Compute the exponential based prefiltering ## window lengths ## ## sf = start frequency ## sw = start window ## ef = end frequency ## ew = end window ## we = window exponent ## np = number of points function w = wslprefilt(sf, sw, ef, ew, we, np) if (nargin != 6) usage("w = wslprefilt(sf, sw, ef, ew, we, np)"); endif # Computes the prefiltering coefficients B = exp(log(sf / ef) / we); Q = ((B * sw) - ew) / (1.0 - B); A = 1.0 / (ef * ((ew + Q) ^ we)); # Computes the window lengths w = ((1.0 ./ (A * linspace(sf,ef,np))) .^ (1 / we)) - Q; endfunctiondrc-3.2.2/source/doc/octave/hhw.m0000644000076400001450000000303711320622700015537 0ustar denisitadm## Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: hh = hhw(fi,f,n) ## ## Generate the Hilbert-Hermitian wavelet ## ## See: http://en.wikipedia.org/wiki/Hilbert-Hermitian_wavelet ## ## fi: fi coefficient, if fi <= 0 then the optimal fi = (2 + sqrt(2))/4 is used ## f: central frequency ## n: number of samples ## function hh = hhw(fi,f,n); # Check if fi needs to be computed if (fi <= 0) fi = (2 + sqrt(2))/4; endif # Computes cfi cfi = sqrt(2) * (((fi ^ -(fi + 0.5)) * gamma(fi + 0.5)) ^ -0.5); # Computes the frequency definition of the wavelet hh = linspace(0, 0.5 * pi * n / (f * ceil(n / 2)), ceil(n / 2)); hh = (cfi * (hh .^ fi)) .* exp(-0.5 * fi * (hh .^ 2)); # Returns the time domain definition of the wavelet hh = fftshift(ifft([hh zeros(1,n - ceil(n / 2))])); endfunctiondrc-3.2.2/source/doc/octave/lrxosim.m0000644000076400001450000000346611320622700016454 0ustar denisitadm## Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: ir = lrxosim(fs,lpir,lpl,lpd,lpf,lpo,hpir,hpl,hpd,hpf,hpo) ## ## Makes an LR24 xover simulation on two input impulse responses, ## returns the resulting combined impulse response. ## ## fs: sample rate ## lpir: lowpass impulse response ## lpl: lowpass level ## lpd: lowpass delay ## lpf: lowpass xover frequency ## lpo: lowpass xover half order ## hpir: highpass impulse response ## hpl: highpass level ## hpd: highpass delay ## hpf: highpass xover frequency ## hpo: highpass xover half order ## ## Example: ## ## ir = lrxosim(44100,ls,1,0,80,2,lm,1,0,80,2); ## function ir = lrxosim(fs,lpir,lpl,lpd,lpf,lpo,hpir,hpl,hpd,hpf,hpo) # Computes the low pass filter [lpb, lpa] = butter(lpo,2 * lpf / fs); # Computes the high pass filter [hpb, hpa] = butter(hpo,2 * hpf / fs,'high'); # Computes the xover impulse response ir = filter(lpb,lpa,filter(lpb,lpa,prepad(lpir(1:(length(lpir)-lpd)),length(lpir)) * lpl)) + filter(hpb,hpa,filter(hpb,hpa,prepad(hpir(1:(length(hpir)-hpd)),length(hpir)) * hpl)); endfunctiondrc-3.2.2/source/doc/octave/erbbwidth.m0000644000076400001450000000211711320622700016721 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: bw = erbbwidth(fp) ## ## Compute the ERB scale bandwidth for an array of ## frequency points ## ## fp = frequency points array function bw = erbbwidth(fp) if (nargin != 1) usage("bw = erbbwidth(fp)"); endif # Computes the bandwidths bw = 0.108 * fp + 24.7; endfunctiondrc-3.2.2/source/doc/octave/cphase.m0000644000076400001450000000234411320622700016214 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: cp = cphase(s) ## ## Computes the continuous phase function of signal s. ## cp = continuous phase, same length of s. function cp = cphase(s) # Get the number of signal samples n = length(s); # Computes the signal spectrum cp = fft(postpad(s(:)',2 * n))(1:n); # Save the reference angle r = angle(cp(1)); # Computes the continuous phase cp(2:n) = r + cumsum(imag(diff(cp) ./ cp(2:n))); cp(1) = r; endfunctiondrc-3.2.2/source/doc/octave/morletw.m0000644000076400001450000000746111320622700016447 0ustar denisitadmfunction [w,t]=morletw(fs,a,b,ki,timeunits,woo) %MORLETW Calculate the Morlet Wavelet. % % W = MORLETW (FS,SC) calculates the Morlet wavelet % at scale SC sampled at rate FS. % % W = MORLETW (FS,SC,SHF) calculates the Morlet wavelet % at scale SC, sampled at rate FS and delayed SHF seconds. % % W = MORLETW (FS,SC,SHF,TIM) calculates the Morlet wavelet % at scale SC, sampled at rate FS and delayed SHF seconds, % changing the time interval to -TIM:TIM seconds. % % W = MORLETW (FS,SC,SHF,TIM,TIMEUNITS) makes the wavelet be % expressed in terms of TIMEUNITS instead of seconds. The default % value of TIMEUNITS is 1 (seconds). Example: 0.001 = milliseconds. % A value of 0 means the default (1). % % W = MORLETW (FS,SC,SHF,TIM,TIMEUNITS,W0) changes the central % frequency of the wavelet to W0. The default value is 2*PI. % % The SC scale wavelet is calculated by compressing or expanding % the scale 1 wavelet. This last is computed in the interval % -TIM:TIM timeunits, and compressions or dilations modify this % interval too. The default value for TIM is 6 time units, since % the values of the Morlet wavelet are negligible for ABS(t)>6 t.u. % % [W,T] = MORLETW (FS,SC,SHF,TIM,TIMEUNITS,W0) also returns % the time basis for the desired wavelet, in TIMEUNITS. % % See also: SCALOG. % %-------------------------------------------------------- % Copyright (C) 1994, 1995, 1996, by Universidad de Vigo % % % Uvi_Wave 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, or (at your option) any % later version. % % Uvi_Wave 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 Uvi_Wave; see the file COPYING. If not, write to the Free % Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. % % Author: Nuria Gonzalez Prelcic % e-mail: Uvi_Wave@tsc.uvigo.es %-------------------------------------------------------- if nargin<3 % The default time shifting value b=0; % is b=0. end if nargin<4 % Default timing [-6 sec. to 6 sec.] ki=6; end if ki<5 fprintf('WARNING: Small time interval. Wavelet ends may be too abrupt.\n'); end % Set the time units to 1 (seconds) as a default value. % When representing scalograms of sampled signals, the % time units must be in the same range that the sampling time % interval (This is documented in SCALOG.M). if nargin<5 timeunits=1; end if timeunits==0 timeunits=1; end fs=fs*timeunits; % We find the number of points according to the sampling rate % and the time space. n=ki*2*fs+1; res=(2*ki)/n; N=(2*ki)*a/res; % Number of points for the scaled wavelet t=linspace(-ki*a,ki*a,N); % Time domain for the scaled wavelet wo=2*pi; % wo=2*pi makes the 1st scale have % the central freq. at 1 Hz if nargin>5 wo=woo; end w=sqrt(1/a)*exp(j*wo*(t-b)/a).*exp(-((t-b)/a).^2/2); drc-3.2.2/source/doc/octave/costable.m0000644000076400001450000000247611320622700016553 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: ct = costable(cv,cd,cn) ## ## Generate a cosine table by recurrence ## ## cv: cosine start value ## sd: cosine delta ## cn: cosine number of values function ct = costable(cv,cd,cn); # Initializes the cos array ct = zeros(1,cn); # Initializes the cosine constants R = sin(cd/2); R = -4 * R * R; S = cos(cv); S = (S * (1 - cos(cd))) - sin(cv) * sin(cd); # Set the first value V = cos(cv); ct(1) = V; # Sine generation loop for I = 2:cn S = R * V + S; V = V + S; ct(I) = V; endfor endfunctiondrc-3.2.2/source/doc/octave/loadpcm.m0000644000076400001450000000207511320622700016371 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage pcm = loadpcm(fname) ## ## load a pcm raw file created by DRC ## ## fname = pcm file name ## the file must be in 32 bit floating point format function pcm = loadpcm(fname) f = fopen(fname,"rb"); [pcm, pcmc] = fread(f,inf,"float32"); fclose(f); endfunction drc-3.2.2/source/doc/octave/ssub.m0000644000076400001450000000364611320622700015733 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: sub = ssub(s,bw) ## ## Computes the smoothed spectral upper bound of signal s on a ## logarithmic frequency scale with bw bandwidth resolution. ## ## s = input signal. ## bw = bandwidth resolution as a faction of octave, for example 0.25 ## means 1/4 of octave resolution. ## sub = output spectral envelope, same length of s. ## function sub = ssub(s,bwidth) # Get the number signal samples n = length(s); # Computes the signal spectrum sp = abs(fft(postpad(s,2 * n)))(1:n); # Computes the half bandwidth hbw = (2 ^ (bwidth / 2)); # Allocates the upper bound array sub = zeros(1,n); # Set the initial max position mp = 0; # Cicles on the signal spectrum for I = 1:n # Computes the upper and lower limit of computation bl = 1 + round((I - 1) / hbw); bu = 1 + round((I - 1) * hbw); # Check the computation limits bu = min(bu,n); # Check if the last max position # has been passed away if (bl > mp) mv = 0; pbu = bl; endif # Get the new max [m, p] = max(sp(pbu:bu)); if (m > mv) mv = m; mp = p; endif sub(I) = mv; pbu = bu + 1; endfor endfunctiondrc-3.2.2/source/doc/octave/irwarp.m0000644000076400001450000000167411320622700016262 0ustar denisitadmfunction res = irwarp(sig,lambda,n) #IRWARP - Computation of a warped impulse response # # y = irwarp(x,lambda,n) # # warp a signal or impulse response (sig) (by allpass1 with lambda) # n = number of samples in the result always stable. # This function uses the dewarping technique, which is more # suitable for warping of an impulse response than longchain # function. # # This function is a part of WarpTB - a Matlab toolbox for # warped signal processing (http://www.acoustics.hut.fi/software/warp/). # See 'help WarpTB' for related functions and examples # Authors: Matti Karjalainen, Aki Hrm # Helsinki University of Technology, Laboratory of Acoustics and # Audio Signal Processing # Adapted to Octave by Denis Sbragion len=length(sig); if nargin<3 n=len; end if nargin<4 Flag=0;end temp = [1 zeros(1,n-1)]; bw = [lambda 1]'; aw = [1 lambda]'; res = sig(1)*temp; for i=2:len temp = filter(bw,aw,temp); res = res+sig(i)*temp; end endfunction drc-3.2.2/source/doc/octave/createdrcplots.m0000644000076400001450000025416013163134455020010 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: createdrcplots(ir1,ic1,it1,ir2,ic2,it2,outdir,fprefix,fext,fdevice) ## ## createdrcplots - Create a full set of eps plots for DRC analysis ## ## ir1 = impulse response 1 ## ic1 = center sample of impulse response 1, -1 for automatic search ## it1 = title for impulse response 1 plots ## ir2 = impulse response 2 ## ic2 = center sample of impulse response 2, -1 for automatic search ## it2 = title for impulse response 2 plots ## outdir = output directory for graph files ## fprefix = prefix for graph files ## fext = extension for graph files, default '.eps' ## fdevice = print device for graph files, default '-depsc2' ## ## Along with the device any other option supported by the Octave ## 'print' command may be specified. For example setting fdevice to: ## ## '-r300 -dpng' ## ## Sets the PNG output device with a resolution of 300 dpi. ## ## Sample rate of ir1 and ir2 *must* be 44.1 kHz ## function createdrcplots(ir1,ic1,it1,ir2,ic2,it2,outdir,fprefix,fext = '.eps',fdevice = '-depsc2') # Find the impulse center if needed if (ic1 < 0) [irm1,ic1] = max(abs(hilbert(ir1))); else irm1 = max(abs(hilbert(ir1))); endif if (ic2 < 0) [irm2,ic2] = max(abs(hilbert(ir2))); else irm2 = max(abs(hilbert(ir2))); endif # Frequency axis tics # gfp = [0.02,0.03,0.05,0.07,0.1,0.15,0.2,0.3,0.5,0.7,1,1.5,2,3,5,7,10,15,20]; # Generate the labels from the tics # gfl = num2str(gfp','%.2g'); # Denser tics, with partial explicit labels gfp = [0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.15,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,1.5,2,3,4,5,6,7,8,9,10,15,20]; gfl = [ "0.02";"0.03";" ";"0.05";" ";"0.07";" ";" ";"0.1";"0.15";"0.2";"0.3";" ";"0.5";" ";"0.7";" ";" ";"1";"1.5";"2";"3";" ";"5";" ";"7";" ";" ";"10";"15";"20" ]; # Normalize the impulse responses to the norm rms1 = norm(ir1); ir1 = ir1(:)/rms1; rms2 = norm(ir2); ir2 = ir2(:)/rms2; # Report the impulse centers disp(sprintf("IR1 impulse center: %d, max: %f, RMS: %f",ic1, irm1, rms1)); disp(sprintf("IR2 impulse center: %d, max: %f, RMS: %f",ic2, irm2, rms2)); fflush(stdout); # Save the sample rate fs = 44100; # Set the default line width DLW = 1.5; # Colormap, line colors and line width for 3d surface plots EDLw = 0.25; EDCMap = hsv2rgb([linspace(0.50,0.00,256)', 1.0 * ones(256,1), 0.65 * ones(256,1)]); ULColor = [0.85, 0.85, 0.85]; LLColor = [0.85, 0.85, 0.85]; # Default font sizes GDFs = 8; # Enable contour display when set to > 0 surcntenable = 0; mapcntenable = 0; # Report the stage disp("Impulse response upsampling..."); fflush(stdout); # Resampling factor rf = 40; # Resampling filter length, cutoff frequency and attenuation rfl = 16383; rcf = 0.95; rat = 160; # Upsample from about -10 to +30 ms irp = 441; ira = 882+441; # Creates the oversampled impulse responses ir1os = rf * iupsample(ir1([ic1-irp:ic1+ira]),rf,rfl,rcf,rat); ir2os = rf * iupsample(ir2([ic2-irp:ic2+ira]),rf,rfl,rcf,rat); # Report the stage disp("Step response..."); fflush(stdout); # Creates the step response ir1step = fftconv(ir1os,ones(1,length(ir1os)))/rf; ir2step = fftconv(ir2os,ones(1,length(ir2os)))/rf; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Set the default font size set(0,"defaultaxesfontsize",GDFs) # Plot the step responses 1 subplot(2,1,1); plot(1000 * ((([0:length(ir1step)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),ir1step,["1;" it1 ";"],"LineWidth",DLW); axis([-5, 25]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g1ax = axis(); # Plot the step responses 2 subplot(2,1,2); plot(1000 * ((([0:length(ir2step)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),ir2step,["3;" it2 ";"],"LineWidth",DLW); axis([-5, 25]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IRStepResponse" fext ],fdevice); # Report the stage disp("Time response, full range..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the oversampled impulse responses 1 subplot(2,1,1); plot(1000 * ((([0:length(ir1os)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),ir1os,["1;" it1 ";"],"LineWidth",DLW); axis([-2, 5]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g1ax = axis(); # Plot the oversampled impulse responses 2 subplot(2,1,2); plot(1000 * ((([0:length(ir2os)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),ir2os,["3;" it2 ";"],"LineWidth",DLW); axis([-2, 5]); #, 1.1 * min(ir2os), 1.1 * max(ir2os)]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IRFullRange" fext ],fdevice); # Remove variables no longer used clear ir1step ir2step; # Computes the analytical signal ir1osh = abs(hilbert(ir1os)); ir2osh = abs(hilbert(ir2os)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the impulse envelope 1 subplot(2,1,1); plot(1000*((([0:length(ir1osh)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),ir1osh,["1;" it1 ";"],"LineWidth",DLW); axis([-2, 5]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g1ax = axis(); # Plot the impulse envelope 2 subplot(2,1,2); plot(1000*((([0:length(ir2osh)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),ir2osh,["3;" it2 ";"],"LineWidth",DLW); axis([-2, 5]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IRFullRangeEnvelope" fext ],fdevice); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the energy-time curve 1 subplot(2,1,1); plot(1000*((([0:length(ir1osh)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),20 * log10(ir1osh),["1;" it1 ";"],"LineWidth",DLW); axis([-2, 5, round(-30 + 20 * log10(max(ir1osh))), round(3 + 20 * log10(max(ir1osh)))]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (dB)"); # Save the axis range g1ax = axis(); # Plot the energy-time curve 2 subplot(2,1,2); plot(1000*((([0:length(ir2osh)-1])/(rf*fs))-((irp/fs) + ((rfl + 1)/(2*rf*fs)))),20 * log10(ir2osh),["3;" it2 ";"],"LineWidth",DLW); axis([-2, 5, round(-30 + 20 * log10(max(ir2osh))), round(3 + 20 * log10(max(ir2osh)))]); axis([-2, 5]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (dB)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IRFullRangeETC" fext ],fdevice); # Remove variables no longer used clear ir1os ir2os ir1osh ir2osh rfl rcf rat; # Report the stage disp("Time response, 2 kHz brickwall..."); fflush(stdout); # Create the 2 kHz brickwall filter fltlen = 4096; fltatt = 160; flt = lowpassfir(fltlen,2000/(fs/2)) .* chebwin(fltlen,fltatt)'; fltdelay = (1 + length(flt)) / 2; # Creates the 2 kHz brickwall filtered impulse responses # about -20 to +50 ms ir1bw = fftconv(flt,ir1([ic1-882:ic1+2205])); ir2bw = fftconv(flt,ir2([ic2-882:ic2+2205])); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the brickwall filtered impulse responses 1 subplot(2,1,1); plot(1000*((([0:length(ir1bw)-1])/fs)-((fltdelay + 882)/fs)),ir1bw,["1;" it1 ";"],"LineWidth",DLW); axis([-20, 50]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g1ax = axis(); # Plot the brickwall filtered impulse responses 2 subplot(2,1,2); plot(1000*((([0:length(ir2bw)-1])/fs)-((fltdelay + 882)/fs)),ir2bw,["3;" it2 ";"],"LineWidth",DLW); axis([-20, 50]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IR2kHzBrickwall" fext ],fdevice); # Computes the analytical signal ir1bwh = abs(hilbert(ir1bw)); ir2bwh = abs(hilbert(ir2bw)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the impulse envelope 1 subplot(2,1,1); plot(1000*((([0:length(ir1bwh)-1])/fs)-((fltdelay + 882)/fs)),ir1bwh,["1;" it1 ";"],"LineWidth",DLW); axis([-20, 50]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g1ax = axis(); # Plot the impulse envelope 2 subplot(2,1,2); plot(1000*((([0:length(ir2bwh)-1])/fs)-((fltdelay + 882)/fs)),ir2bwh,["3;" it2 ";"],"LineWidth",DLW); axis([-20, 50]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (normalized)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IR2kHzBrickwallEnvelope" fext ],fdevice); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the energy-time curve 1 subplot(2,1,1); plot(1000*((([0:length(ir1bwh)-1])/fs)-((fltdelay + 882)/fs)),20 * log10(ir1bwh),["1;" it1 ";"],"LineWidth",DLW); axis([-20, 50, round(-30 + 20 * log10(max(ir1bwh))), round(3 + 20 * log10(max(ir1bwh)))]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (dB)"); # Save the axis range g1ax = axis(); # Plot the energy-time curve 2 subplot(2,1,2); plot(1000*((([0:length(ir2bwh)-1])/fs)-((fltdelay + 882)/fs)),20 * log10(ir2bwh),["3;" it2 ";"],"LineWidth",DLW); axis([-20, 50, round(-30 + 20 * log10(max(ir2bwh))), round(3 + 20 * log10(max(ir2bwh)))]); grid("on"); xlabel("Time (ms)"); ylabel("Amplitude (dB)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IR2kHzBrickwallETC" fext ],fdevice); # Remove variables no longer used clear ir1bw ir2bw ir1bwh ir2bwh; # Report the stage disp("Time response, 200 Hz brickwall..."); fflush(stdout); # Create the 200 Hz brickwall filter fltlen = 32768; fltatt = 160; flt = lowpassfir(fltlen,200/(fs/2)) .* chebwin(fltlen,fltatt)'; fltdelay = (1 + length(flt)) / 2; # Creates the 200 Hz brickwall filtered impulse responses # about -200 to +500 ms ir1bw = fftconv(flt,ir1([ic1-8820:ic1+22050])); ir2bw = fftconv(flt,ir2([ic2-8820:ic2+22050])); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the brickwall filtered impulse responses 1 subplot(2,1,1); plot(((([0:length(ir1bw)-1])/fs)-((fltdelay + 8820)/fs)),ir1bw,["1;" it1 ";"],"LineWidth",DLW); axis([-0.2, 0.5]); grid("on"); xlabel("Time (s)"); ylabel("Amplitude (normalized)"); # Save the axis range g1ax = axis(); # Plot the brickwall filtered impulse responses 2 subplot(2,1,2); plot(((([0:length(ir2bw)-1])/fs)-((fltdelay + 8820)/fs)),ir2bw,["3;" it2 ";"],"LineWidth",DLW); axis([-0.2, 0.5]); grid("on"); xlabel("Time (s)"); ylabel("Amplitude (normalized)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IR200HzBrickwall" fext ],fdevice); # Computes the analytical signal ir1bwh = abs(hilbert(ir1bw)); ir2bwh = abs(hilbert(ir2bw)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the impulse envelope 1 subplot(2,1,1); plot(((([0:length(ir1bwh)-1])/fs)-((fltdelay + 8820)/fs)),ir1bwh,["1;" it1 ";"],"LineWidth",DLW); axis([-0.2, 0.5]); grid("on"); xlabel("Time (s)"); ylabel("Amplitude (normalized)"); # Save the axis range g1ax = axis(); # Plot the impulse envelope 2 subplot(2,1,2); plot(((([0:length(ir2bwh)-1])/fs)-((fltdelay + 8820)/fs)),ir2bwh,["3;" it2 ";"],"LineWidth",DLW); axis([-0.2, 0.5]); grid("on"); xlabel("Time (s)"); ylabel("Amplitude (normalized)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IR200HzBrickwallEnvelope" fext ],fdevice); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the energy-time curve 1 subplot(2,1,1); plot(((([0:length(ir1bwh)-1])/fs)-((fltdelay + 8820)/fs)),20 * log10(ir1bwh),["1;" it1 ";"],"LineWidth",DLW); axis([-0.2, 0.5, round(-30 + 20 * log10(max(ir1bwh))), round(3 + 20 * log10(max(ir1bwh)))]); grid("on"); xlabel("Time (s)"); ylabel("Amplitude (dB)"); # Save the axis range g1ax = axis(); # Plot the energy-time curve 2 subplot(2,1,2); plot(((([0:length(ir2bwh)-1])/fs)-((fltdelay + 8820)/fs)),20 * log10(ir2bwh),["3;" it2 ";"],"LineWidth",DLW); axis([-0.2, 0.5, round(-30 + 20 * log10(max(ir2bwh))), round(3 + 20 * log10(max(ir2bwh)))]); grid("on"); xlabel("Time (s)"); ylabel("Amplitude (dB)"); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set the uniforma axis range subplot(2,1,1); axis(gax); subplot(2,1,2); axis(gax); # Print to the output file print([ outdir fprefix "-IR200HzBrickwallETC" fext ],fdevice); # Remove variables no longer used clear ir1bw ir2bw ir1bwh ir2bwh; # Report the stage disp("Unsmoothed frequency response, 1 ms window..."); fflush(stdout); # Computes the window, 1 ms wind = [ones(1,441) ones(1,22) (blackman(44)(23:44))' zeros(1,8192 - (441 + 44))]'; # Estract the windowed impulse responses ir1w = ir1([ic1-441:ic1+(8192 - (441 + 1))]) .* wind; ir2w = ir2([ic2-441:ic2+(8192 - (441 + 1))]) .* wind; # Rotate the impulse response and transform to the frequency domain ir1w = fft([ir1w(442:length(ir1w))' ir1w(1:441)']); ir2w = fft([ir2w(442:length(ir2w))' ir2w(1:441)']); # Compute the index limits ixl = floor(1000 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the magnitude response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),20 * log10(abs(ir1w(1 + ixg))),["1;" it1 ";"],"LineWidth",DLW); axis([1, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Amplitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g1ax = axis(); # Plot the magnitude response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),20 * log10(abs(ir2w(1 + ixg))),["3;" it2 ";"],"LineWidth",DLW); axis([1, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Amplitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Print to the output file print([ outdir fprefix "-MRUnsmoothed1ms" fext ],fdevice); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the phase response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),180 * angle(ir1w(1 + ixg))/pi,["1;" it1 ";"],"LineWidth",DLW); axis([1, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Plot the phase response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),180 * angle(ir2w(1 + ixg))/pi,["3;" it2 ";"],"LineWidth",DLW); axis([1, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Print to the output file print([ outdir fprefix "-PRUnsmoothed1ms" fext ],fdevice); # Report the stage disp("Unsmoothed frequency response, 5 ms window..."); fflush(stdout); # Computes the window, 5 ms wind = [ones(1,441) ones(1,110) (blackman(220)(111:220))' zeros(1,8192 - (441 + 220))]'; # Estract the windowed impulse responses ir1w = ir1([ic1-441:ic1+(8192 - (441 + 1))]) .* wind; ir2w = ir2([ic2-441:ic2+(8192 - (441 + 1))]) .* wind; # Rotate the impulse response and transform to the frequency domain ir1w = fft([ir1w(442:length(ir1w))' ir1w(1:441)']); ir2w = fft([ir2w(442:length(ir2w))' ir2w(1:441)']); # Compute the index limits ixl = floor(200 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the magnitude response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),20 * log10(abs(ir1w(1 + ixg))),["1;" it1 ";"],"LineWidth",DLW); axis([0.2, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Amplitude (dB)"); safetics("x",gfp,gfl); safetics("y",-15:3:15); # Save the axis range g1ax = axis(); # Plot the magnitude response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),20 * log10(abs(ir2w(1 + ixg))),["3;" it2 ";"],"LineWidth",DLW); axis([0.2, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Amplitude (dB)"); safetics("x",gfp,gfl); safetics("y",-15:3:15); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Print to the output file print([ outdir fprefix "-MRUnsmoothed5ms" fext ],fdevice); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the phase response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),180 * angle(ir1w(1 + ixg))/pi,["1;" it1 ";"],"LineWidth",DLW); axis([0.2, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Plot the phase response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),180 * angle(ir2w(1 + ixg))/pi,["3;" it2 ";"],"LineWidth",DLW); axis([0.2, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Print to the output file print([ outdir fprefix "-PRUnsmoothed5ms" fext ],fdevice); # Report the stage disp("Unsmoothed frequency response, 200 ms window..."); fflush(stdout); # Computes the window, 200 ms wind = [ones(1,8820) ones(1,4410) (blackman(8820)(4411:8820))' zeros(1,32768 - (8820 + 8820))]'; # Estract the windowed impulse responses ir1w = ir1([ic1-8820:ic1+(32768 - (8820 + 1))]) .* wind; ir2w = ir2([ic2-8820:ic2+(32768 - (8820 + 1))]) .* wind; # Rotate and pad the impulse response and transform to the frequency domain ir1w = fft([ir1w(8821:length(ir1w))' zeros(1,131072 - length(ir1w)) ir1w(1:8820)']); ir2w = fft([ir2w(8821:length(ir2w))' zeros(1,131072 - length(ir2w)) ir2w(1:8820)']); # Compute the index limits ixl = floor(20 * length(ir1w) / fs); ixu = ceil(200 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the magnitude response 1 subplot(2,1,1); semilogx(fs * ixg / length(ir1w),20 * log10(abs(ir1w(1 + ixg))),["1;" it1 ";"],"LineWidth",DLW); axis([20, 200]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Amplitude (dB)"); safetics("x",1000 * gfp,gfl); # Save the axis range g1ax = axis(); # Plot the magnitude response 2 subplot(2,1,2); semilogx(fs * ixg / length(ir2w),20 * log10(abs(ir2w(1 + ixg))),["3;" it2 ";"],"LineWidth",DLW); axis([20, 200]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Amplitude (dB)"); safetics("x",1000 * gfp,gfl); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Print to the output file print([ outdir fprefix "-MRUnsmoothed200ms" fext ],fdevice); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the phase response 1 subplot(2,1,1); semilogx(fs * ixg / length(ir1w),180 * angle(ir1w(1 + ixg))/pi,["1;" it1 ";"],"LineWidth",DLW); axis([20, 200, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",1000 * gfp,gfl); safetics("y",-180:30:180); # Plot the phase response 2 subplot(2,1,2); semilogx(fs * ixg / length(ir2w),180 * angle(ir2w(ixg))/pi,["3;" it2 ";"],"LineWidth",DLW); axis([20, 200, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",1000 * gfp,gfl); safetics("y",-180:30:180); # Print to the output file print([ outdir fprefix "-PRUnsmoothed200ms" fext ],fdevice); # Remove variables no longer used clear wind ir1w ir2w; # Report the stage disp("Frequency dependent windowing, magnitude response, 1/3 oct settings..."); fflush(stdout); # Estract the windowed impulse responses ir1w = ir1(ic1-32767:ic1+32768); ir2w = ir2(ic2-32767:ic2+32768); # Extract the minimum phase impulse response [ir1cps, ir1w] = rceps(ir1w); [ir2cps, ir2w] = rceps(ir2w); clear ir1cps ir2cps; # Performs the frequency dependant windowing ir1w = irslprefilt(ir1w,1,2 * 20/fs,4761,2 * 20000/fs,5,1.0,4096,1.0,5,0); ir2w = irslprefilt(ir2w,1,2 * 20/fs,4761,2 * 20000/fs,5,1.0,4096,1.0,5,0); # Pad the windowed impulse response ir1w = [ zeros(1,65536 - length(ir1w)) ir1w(:)' ]; ir2w = [ zeros(1,65536 - length(ir2w)) ir2w(:)' ]; # Computes the magnitude response ir1m = abs(fft(ir1w)); ir2m = abs(fft(ir2w)); # Compute the index limits ixl = floor(20 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the magnitude response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),20 * log10(ir1m(1 + ixg)),["1;" it1 ";"],"LineWidth",DLW); axis([0.02, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g1ax = axis(); # Plot the magnitude response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),20 * log10(ir2m(1 + ixg)),["3;" it2 ";"],"LineWidth",DLW); axis([0.02, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Print to the output file print([ outdir fprefix "-MRFDWSmoothed-1-3" fext ],fdevice); # Report the stage disp("Frequency dependent windowing, phase response, 1/3 oct settings..."); fflush(stdout); # Estract the windowed impulse responses ir1w = ir1([ic1-4096:ic1+32767]); ir2w = ir2([ic2-4096:ic2+32767]); # Performs the frequency dependant windowing ir1w = irslprefilt(ir1w,4097,2 * 20/fs,4761,2 * 20000/fs,5,1.0,4096,1.0,5,4096); ir2w = irslprefilt(ir2w,4097,2 * 20/fs,4761,2 * 20000/fs,5,1.0,4096,1.0,5,4096); # Rotate the impulse response and transform to the frequency domain ir1w = fft([ir1w(4097:length(ir1w)) ir1w(1:4096)]); ir2w = fft([ir2w(4097:length(ir2w)) ir2w(1:4096)]); # Compute the index limits ixl = floor(20 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the phase response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),180 * angle(ir1w(1 + ixg))/pi,["1;" it1 ";"],"LineWidth",DLW); axis([0.02, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Plot the phase response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),180 * angle(ir2w(ixg))/pi,["3;" it2 ";"],"LineWidth",DLW); axis([0.02, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Print to the output file print([ outdir fprefix "-PRFDWSmoothed-1-3" fext ],fdevice); # Report the stage disp("Frequency dependent windowing, magnitude response, 1/6 oct settings..."); fflush(stdout); # Estract the windowed impulse responses ir1w = ir1(ic1-32767:ic1+32768); ir2w = ir2(ic2-32767:ic2+32768); # Extract the minimum phase impulse response [ir1cps, ir1w] = rceps(ir1w); [ir2cps, ir2w] = rceps(ir2w); clear ir1cps ir2cps; # Performs the frequency dependant windowing ir1w = irslprefilt(ir1w,1,2 * 20/fs,9538,2 * 20000/fs,10,1.0,4096,1.0,10,0); ir2w = irslprefilt(ir2w,1,2 * 20/fs,9538,2 * 20000/fs,10,1.0,4096,1.0,10,0); # Pad the windowed impulse response ir1w = [ zeros(1,65536 - length(ir1w)) ir1w(:)' ]; ir2w = [ zeros(1,65536 - length(ir2w)) ir2w(:)' ]; # Computes the magnitude response ir1m = abs(fft(ir1w)); ir2m = abs(fft(ir2w)); # Compute the index limits ixl = floor(20 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the magnitude response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),20 * log10(ir1m(1 + ixg)),["1;" it1 ";"],"LineWidth",DLW); axis([0.02, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g1ax = axis(); # Plot the magnitude response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),20 * log10(ir2m(1 + ixg)),["3;" it2 ";"],"LineWidth",DLW); axis([0.02, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Print to the output file print([ outdir fprefix "-MRFDWSmoothed-1-6" fext ],fdevice); # Report the stage disp("Frequency dependent windowing, phase response, 1/6 oct settings..."); fflush(stdout); # Estract the windowed impulse responses ir1w = ir1([ic1-4096:ic1+32767]); ir2w = ir2([ic2-4096:ic2+32767]); # Performs the frequency dependant windowing ir1w = irslprefilt(ir1w,4097,2 * 20/fs,9538,2 * 20000/fs,10,1.0,4096,1.0,10,4096); ir2w = irslprefilt(ir2w,4097,2 * 20/fs,9538,2 * 20000/fs,10,1.0,4096,1.0,10,4096); # Rotate the impulse response and transform to the frequency domain ir1w = fft([ir1w(4097:length(ir1w)) ir1w(1:4096)]); ir2w = fft([ir2w(4097:length(ir2w)) ir2w(1:4096)]); # Compute the index limits ixl = floor(20 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the phase response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),180 * angle(ir1w(1 + ixg))/pi,["1;" it1 ";"],"LineWidth",DLW); axis([0.02, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Plot the phase response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),180 * angle(ir2w(1 + ixg))/pi,["3;" it2 ";"],"LineWidth",DLW); axis([0.02, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Print to the output file print([ outdir fprefix "-PRFDWSmoothed-1-6" fext ],fdevice); # Report the stage disp("Frequency dependent windowing, magnitude response, normal.drc settings..."); fflush(stdout); # Estract the windowed impulse responses ir1w = ir1(ic1-32767:ic1+32768); ir2w = ir2(ic2-32767:ic2+32768); # Extract the minimum phase impulse response [ir1cps, ir1w] = rceps(ir1w); [ir2cps, ir2w] = rceps(ir2w); clear ir1cps ir2cps; # Performs the frequency dependant windowing ir1w = irslprefilt(ir1w,1,2 * 20/fs,22050,2 * 20000/fs,22,1.0,4096,0.25,22,0); ir2w = irslprefilt(ir2w,1,2 * 20/fs,22050,2 * 20000/fs,22,1.0,4096,0.25,22,0); # Pad the windowed impulse response ir1w = [ zeros(1,65536 - length(ir1w)) ir1w(:)' ]; ir2w = [ zeros(1,65536 - length(ir2w)) ir2w(:)' ]; # Computes the magnitude response ir1m = abs(fft(ir1w)); ir2m = abs(fft(ir2w)); # Compute the index limits ixl = floor(20 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the magnitude response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),20 * log10(ir1m(1 + ixg)),["1;" it1 ";"],"LineWidth",DLW); axis([0.02, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g1ax = axis(); # Plot the magnitude response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),20 * log10(ir2m(1 + ixg)),["3;" it2 ";"],"LineWidth",DLW); axis([0.02, 20]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); safetics("x",gfp,gfl); # Save the axis range g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Print to the output file print([ outdir fprefix "-MRFDWSmoothed" fext ],fdevice); # Report the stage disp("Frequency dependent windowing, phase response, normal.drc settings..."); fflush(stdout); # Estract the windowed impulse responses ir1w = ir1([ic1-4096:ic1+32767]); ir2w = ir2([ic2-4096:ic2+32767]); # Performs the frequency dependant windowing ir1w = irslprefilt(ir1w,4097,2 * 20/fs,22050,2 * 20000/fs,22,1.0,4096,0.25,22,4096); ir2w = irslprefilt(ir2w,4097,2 * 20/fs,22050,2 * 20000/fs,22,1.0,4096,0.25,22,4096); # Rotate the impulse response and transform to the frequency domain ir1w = fft([ir1w(4097:length(ir1w)) ir1w(1:4096)]); ir2w = fft([ir2w(4097:length(ir2w)) ir2w(1:4096)]); # Compute the index limits ixl = floor(20 * length(ir1w) / fs); ixu = ceil(20000 * length(ir1w) / fs); ixg = ixl:ixu; # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the phase response 1 subplot(2,1,1); semilogx(0.001 * fs * ixg / length(ir1w),180 * angle(ir1w(1 + ixg))/pi,["1;" it1 ";"],"LineWidth",DLW); axis([0.02, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Plot the phase response 2 subplot(2,1,2); semilogx(0.001 * fs * ixg / length(ir2w),180 * angle(ir2w(1 + ixg))/pi,["3;" it2 ";"],"LineWidth",DLW); axis([0.02, 20, -180, 180]); grid("on"); xlabel("Frequency (kHz)"); ylabel("Phase (deg)"); safetics("x",gfp,gfl); safetics("y",-180:30:180); # Print to the output file print([ outdir fprefix "-PRFDWSmoothed" fext ],fdevice); # Report the stage disp("Bark smoothed magnitude response..."); fflush(stdout); # Windows array, in ms wlst = [ 200 100 50 20 10 5 2 1 ]; # Graph resolution gres = 16384; # Graph pregap gpgp = 441; # Scaling base (dB) scbs = 18; # Scaling delta (dB) scdt = -3; # Compute the index limits ixl = floor(2 * 20 * gres / fs); ixu = ceil(2 * 20000 * gres / fs); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Enable holding the plot subplot(2,1,1); hold("on"); subplot(2,1,2); hold("on"); # Cycle on the windows sizes cscl = scbs; cg = 1; for cws = wlst # Computes the number of samples for the current window wns = round(fs * cws / (2 * 1000)); # Creates the response prewindow wind = [ones(1,gpgp) ones(1,wns) (blackman(2 * wns)((wns + 1):(2 * wns)))' zeros(1,gres - (gpgp + 2 * wns))]'; # Extract the windowed impulse responses ir1w = ir1([(ic1 - gpgp):(ic1 + (gres - (gpgp + 1)))]) .* wind; ir2w = ir2([(ic2 - gpgp):(ic2 + (gres - (gpgp + 1)))]) .* wind; # Computes the smoothed magnitude response ir1m = ssev(ir1w,fs,-1,1); ir2m = ssev(ir2w,fs,-1,1); # Computes the graph lower bounds glb = fs / (4 * wns); glb = round(glb / (fs / (2 * gres))); glb = max(glb,2); # Computes the graph index ixg = max(ixl,glb):ixu; # Plot the magnitude response subplot(2,1,1); # semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir1m(1 + ixg)),["1;" it1 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ";"],"color",hsv2rgb([0, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir1m(1 + ixg)),"color",hsv2rgb([0, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); subplot(2,1,2); # semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir2m(1 + ixg)),["3;" it2 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ";"],"color",hsv2rgb([2/3, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir2m(1 + ixg)),"color",hsv2rgb([2/3, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); # Adjust the scaling cscl = cscl + scdt; cg = cg + 1; endfor # Disable holding the plot and set graph parameters subplot(2,1,1); hold("off"); safetics("x",gfp,gfl); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); grid("on"); # legend("location","southwest"); legend("off"); subplot(2,1,2); hold("off"); safetics("x",gfp,gfl); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); grid("on"); # legend("location","southwest"); legend("off"); # Save the axis range subplot(2,1,1); axis([0.02, 20]); g1ax = axis(); subplot(2,1,2); axis([0.02, 20]); g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Cycle on the windows sizes cscl = scbs; for cws = wlst # Add the plot labels subplot(2,1,1); text(0.02,gax(3) + cscl - scdt - scdt / 2,[ it1 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ],'fontsize',GDFs); subplot(2,1,2); text(0.02,gax(3) + cscl - scdt - scdt / 2,[ it2 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ],'fontsize',GDFs); # Adjust the scaling cscl = cscl + scdt; endfor # Print to the output file print([ outdir fprefix "-MRBarkSmoothed" fext ],fdevice); # Report the stage disp("ERB smoothed magnitude response..."); fflush(stdout); # Windows array, in ms wlst = [ 200 100 50 20 10 5 2 1 ]; # Graph resolution gres = 16384; # Graph pregap gpgp = 441; # Scaling base (dB) scbs = 18; # Scaling delta (dB) scdt = -3; # Compute the index limits ixl = floor(2 * 20 * gres / fs); ixu = ceil(2 * 20000 * gres / fs); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Enable holding the plot subplot(2,1,1); hold("on"); subplot(2,1,2); hold("on"); # Cycle on the windows sizes cscl = scbs; cg = 1; for cws = wlst # Computes the number of samples for the current window wns = round(fs * cws / (2 * 1000)); # Creates the response prewindow wind = [ones(1,gpgp) ones(1,wns) (blackman(2 * wns)((wns + 1):(2 * wns)))' zeros(1,gres - (gpgp + 2 * wns))]'; # Extract the windowed impulse responses ir1w = ir1([(ic1 - gpgp):(ic1 + (gres - (gpgp + 1)))]) .* wind; ir2w = ir2([(ic2 - gpgp):(ic2 + (gres - (gpgp + 1)))]) .* wind; # Computes the smoothed magnitude response ir1m = ssev(ir1w,fs,-2,1); ir2m = ssev(ir2w,fs,-2,1); # Computes the graph lower bounds glb = fs / (4 * wns); glb = round(glb / (fs / (2 * gres))); glb = max(glb,2); # Computes the graph index ixg = max(ixl,glb):ixu; # Plot the magnitude response subplot(2,1,1); # semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir1m(1 + ixg)),["1;" it1 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ";"],"color",hsv2rgb([0, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir1m(1 + ixg)),"color",hsv2rgb([0, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); subplot(2,1,2); # semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir2m(1 + ixg)),["3;" it2 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ";"],"color",hsv2rgb([2/3, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); semilogx(0.001 * 0.5 * fs * ixg / gres,cscl + 20 * log10(ir2m(1 + ixg)),"color",hsv2rgb([2/3, 1, 0.5 + 0.5 * cg / length(wlst)]),"LineWidth",DLW); # Adjust the scaling cscl = cscl + scdt; cg = cg + 1; endfor # Disable holding the plot and set graph parameters subplot(2,1,1); hold("off"); safetics("x",gfp,gfl); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); grid("on"); # legend("location","southwest"); legend("off"); subplot(2,1,2); hold("off"); safetics("x",gfp,gfl); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); grid("on"); # legend("location","southwest"); legend("off"); # Save the axis range subplot(2,1,1); axis([0.02, 20]); g1ax = axis(); subplot(2,1,2); axis([0.02, 20]); g2ax = axis(); # Computes the uniform axis range gax = g1ax; gax(3) = min(g1ax(3),g2ax(3)); gax(4) = max(g1ax(4),g2ax(4)); # Set a minimum range of 30 dB if ((gax(4) - gax(3)) < 30) gax(4) = round(gax(4) + (30 - (gax(4) - gax(3))) / 2); gax(3) = gax(4) - 30; endif # Round up to 3 dB steps gax(3) = 3 * floor(gax(3) / 3); gax(4) = 3 * ceil(gax(4) / 3); # Set the uniforma axis range subplot(2,1,1); axis(gax); safetics("y",gax(3):3:gax(4)); subplot(2,1,2); axis(gax); safetics("y",gax(3):3:gax(4)); # Cycle on the windows sizes cscl = scbs; for cws = wlst # Add the plot labels subplot(2,1,1); text(0.02,gax(3) + cscl - scdt - scdt / 2,[ it1 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ],'fontsize',GDFs); subplot(2,1,2); text(0.02,gax(3) + cscl - scdt - scdt / 2,[ it2 sprintf(" (%.1f ms, %+.1f dB)",cws,cscl) ],'fontsize',GDFs); # Adjust the scaling cscl = cscl + scdt; endfor # Print to the output file print([ outdir fprefix "-MRERBSmoothed" fext ],fdevice); # Remove variables no longer used clear wind ir1w ir1m ir2w ir2m ixl ixu ixg g1ax g2ax gax; # Report the stage disp("Spectral decay and formation, high range..."); fflush(stdout); # Spectrogram from -1 to +2 ms tbs = 1; tbe = 2; sbs = 44; sas = 88; sfs = 64; sol = 1; # 0.5 ms spectrogram window swl = 22; # Computes the spectrogram window, wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1((ic1 - (-1 + sbs + swl/2)):(ic1 + (sas + sfs))),sfs,fs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2((ic2 - (-1 + sbs + swl/2)):(ic2 + (sas + sfs))),sfs,fs,wind,sfs - sol); # Normalize and truncates the spectral decay S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(-30/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SDHighRange" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SFHighRange" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Report the stage disp("Spectral decay and formation, mid range..."); fflush(stdout); # Spectrogram from -10 to +20 ms tbs = 10; tbe = 20; sbs = 441; sas = 882; sfs = 1024; sol = 10; # 5 ms spectrogram window swl = 220; # Computes the spectrogram window wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1((ic1 - (-1 + sbs + swl/2)):(ic1 + (sas + sfs))),sfs,fs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2((ic2 - (-1 + sbs + swl/2)):(ic2 + (sas + sfs))),sfs,fs,wind,sfs - sol); # Normalize and truncates the spectral decay S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(-30/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SDMidRange" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SFMidRange" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Report the stage disp("Spectral decay and formation, bass range..."); fflush(stdout); # Spectrogram from -0.10 to +0.20 s tbs = 0.10; tbe = 0.20; sbs = 4410; sas = 8820; sfs = 1024; sol = 10; # 50 ms spctrogram window swl = 220; # Downsample the impulse response 10 times to speed up the spectrogram computation dsdf = 10; dsfs = fs/dsdf; dsfl = 16383; dsfd = (dsfl + 1) / (2 * fs); ir1ds = idownsample(ir1(ic1 - (-10 + sbs + swl * 5):ic1 + (sas + sfs * 10)),dsdf,dsfl,0.5,160); ir2ds = idownsample(ir2(ic2 - (-10 + sbs + swl * 5):ic2 + (sas + sfs * 10)),dsdf,dsfl,0.5,160); # Computes the spectrogram window, wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1ds,sfs,dsfs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2ds,sfs,dsfs,wind,sfs - sol); # Normalize and truncates the spectral decay S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(-30/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SDBassRange" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SFBassRange" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Report the stage disp("Spectral decay and formation, high range, wider window..."); fflush(stdout); # Spectrogram from -2 to +4 ms tbs = 2; tbe = 4; sbs = 88; sas = 176; sfs = 64; sol = 1; # 1 ms spectrogram window swl = 44; # Computes the spectrogram window, wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1((ic1 - (-1 + sbs + swl/2)):(ic1 + (sas + sfs))),sfs,fs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2((ic2 - (-1 + sbs + swl/2)):(ic2 + (sas + sfs))),sfs,fs,wind,sfs - sol); # Normalize and truncates the spectral decay S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(-30/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SDHighRangeW" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 2, 20, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SFHighRangeW" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Report the stage disp("Spectral decay and formation, mid range, wider window..."); fflush(stdout); # Spectrogram from -20 to +40 ms tbs = 20; tbe = 40; sbs = 882; sas = 1764; sfs = 1024; sol = 10; # 10 ms spectrogram window swl = 440; # Computes the spectrogram window wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1((ic1 - (-1 + sbs + swl/2)):(ic1 + (sas + sfs))),sfs,fs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2((ic2 - (-1 + sbs + swl/2)):(ic2 + (sas + sfs))),sfs,fs,wind,sfs - sol); # Normalize and truncates the spectral decay S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(-30/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SDMidRangeW" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t1 - (sbs/fs)),0.001 * f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(1000 * (t2 - (sbs/fs)),0.001 * f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 0.2, 2, -33, 1]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SFMidRangeW" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Report the stage disp("Spectral decay and formation, bass range, wider window..."); fflush(stdout); # Spectrogram from -0.20 to +0.40 s tbs = 0.20; tbe = 0.40; sbs = 8820; sas = 17640; sfs = 1024; sol = 20; # 100 ms spctrogram window swl = 440; # Downsample the impulse response 10 times to speed up the spectrogram computation dsdf = 10; dsfs = fs/dsdf; dsfl = 16383; dsfd = (dsfl + 1) / (2 * fs); ir1ds = idownsample(ir1(ic1 - (-10 + sbs + swl * 5):ic1 + (sas + sfs * 10)),dsdf,dsfl,0.5,160); ir2ds = idownsample(ir2(ic2 - (-10 + sbs + swl * 5):ic2 + (sas + sfs * 10)),dsdf,dsfl,0.5,160); # Computes the spectrogram window, wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1ds,sfs,dsfs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2ds,sfs,dsfs,wind,sfs - sol); # Normalize and truncates the spectral decay S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(-30/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SDBassRangeW" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral decay 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(t1 - (dsfd + sbs/fs),f1,S1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it1); # Plot the spectral decay 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(t2 - (dsfd + sbs/fs),f2,S2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([-tbs, tbe, 20, 200, -33, 1]); grid("on"); xlabel("Time (s)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("y",1000 * gfp,gfl); safetics("z",-30:6:0); view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-SFBassRangeW" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Remove variables no longer used clear dsdf dsfs dsfl dsfd; clear wind S1 f1 t1 S2 f2 t2 ir1ds ir2ds sbs sas sfs sol swl; # Report the stage disp("Spectrogram, 1 ms window..."); fflush(stdout); # Spectrogram from -10 to +40 ms tbs = 10; tbe = 40; sbs = 441; sas = 1764; sfs = 512; sol = 4; mlb = -90; # 1 ms spectrogram window swl = 44; # Spaziatura tics asse x e y xtsp = 2.5; ytsp = 2; # Computes the spectrogram window wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1((ic1 - (-1 + sbs + swl/2)):(ic1 + (sas + sfs))),sfs,fs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2((ic2 - (-1 + sbs + swl/2)):(ic2 + (sas + sfs))),sfs,fs,wind,sfs - sol); # Normalize the spectrogram S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(mlb/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(mlb/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectrogram 1 subplot(2,1,1); imagesc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1); set(gca(),"ydir","normal"); axis([-tbs, tbe, 0, fs / 2000]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); text(1.1 * tbe,fs / 4000,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",-tbs:xtsp:tbe); safetics("y",0:ytsp:(fs / 2000)); colormap(EDCMap); colorbar("EastOutside"); title(it1); # Plot the spectrogram 2 subplot(2,1,2); imagesc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2); set(gca(),"ydir","normal"); axis([-tbs, tbe, 0, fs / 2000]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",-tbs:xtsp:tbe); safetics("y",0:ytsp:(fs / 2000)); text(1.1 * tbe,fs / 4000,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); colormap(EDCMap); colorbar("EastOutside"); title(it2); # Print to the output file print([ outdir fprefix "-Spectrogram01ms" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Report the stage disp("Spectrogram, 20 ms window..."); fflush(stdout); # Spectrogram from -100 to +400 ms tbs = 100; tbe = 400; sbs = 4410; sas = 17640; sfs = 1024; sol = 20; mlb = -90; # 20 ms spectrogram window swl = 882; # Spaziatura tics asse x e y xtsp = 25; ytsp = 2; # Computes the spectrogram window wind = [blackman(swl)' zeros(1,sfs-swl)]'; # Computes the spectrograms [S1, f1, t1] = specgram(ir1((ic1 - (-1 + sbs + swl/2)):(ic1 + (sas + sfs))),sfs,fs,wind,sfs - sol); [S2, f2, t2] = specgram(ir2((ic2 - (-1 + sbs + swl/2)):(ic2 + (sas + sfs))),sfs,fs,wind,sfs - sol); # Normalize the spectrogram S1 = abs(S1); S1 = S1/max(S1(:)); S1 = 20 * log10(max(S1,10^(mlb/20))); S2 = abs(S2); S2 = S2/max(S2(:)); S2 = 20 * log10(max(S2,10^(mlb/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectrogram 1 subplot(2,1,1); imagesc(1000 * (t1 - (sbs/fs)),0.001 * f1,S1); set(gca(),"ydir","normal"); axis([-tbs, tbe, 0, fs / 2000]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",-tbs:xtsp:tbe); safetics("y",0:ytsp:(fs / 2000)); text(1.1 * tbe,fs / 4000,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); colormap(EDCMap); colorbar("EastOutside"); title(it1); # Plot the spectrogram 2 subplot(2,1,2); imagesc(1000 * (t2 - (sbs/fs)),0.001 * f2,S2); set(gca(),"ydir","normal"); axis([-tbs, tbe, 0, fs / 2000]); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",-tbs:xtsp:tbe); safetics("y",0:ytsp:(fs / 2000)); text(1.1 * tbe,fs / 4000,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); colormap(EDCMap); colorbar("EastOutside"); title(it2); # Print to the output file print([ outdir fprefix "-Spectrogram20ms" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Remove variables no longer used clear S1 S2; # Report the stage disp("Morlet cycle/octave scalogram, high time resolution..."); fflush(stdout); # Morlet scalogram from -10 cicles to +20 cycles # 20 Hz to 20 kHz # 100 frequency points and 350 cicle points cecb = -10; cece = 20; cenc = 350; cesf = 20; ceef = 20000; cenf = 100; # Parametri upsampling e filtro cefl = 32768; ceat = 120; ceuf = 8; cewm = 0.5; # Morlet wavelet ceft = 2; # Spaziatura tics asse x xtsp = 2; # Computes the cicle points cecp = linspace(cecb,cece,cenc); # Computes the frequency points cebs = 2 ^ (log2(ceef / cesf) / cenf); cefp = logspace(log10(2 * cesf / (cebs * fs)),log10(2 * ceef / (cebs * fs)),cenf); # Computes the Morlet cycle/octave scalogram ce1 = tfir(ir1, ic1, cecp, cefp, cefl, ceat, ceuf, ceft, cewm); ce2 = tfir(ir2, ic2, cecp, cefp, cefl, ceat, ceuf, ceft, cewm); # Computes the envelope for I = 1:cenf ce1(I,:) = abs(hilbert(ce1(I,:))); ce2(I,:) = abs(hilbert(ce2(I,:))); endfor # Perform the scalogram interpolation # Not effective, so disabled cpif = 1; fpif = 1; # Check if interpolation is required if (cpif > 1 || fpif > 1) # Computes the interpolation cicle points itcp = linspace(cecb,cece,cenc * cpif); # Computes the frequency points itfp = logspace(log10(2 * cesf / (cebs * fs)),log10(2 * ceef / (cebs * fs)),cenf * fpif); # Interpolates the envelope ce1 = pchip2d(cecp,cefp,ce1,itcp(:)',itfp(:)); ce2 = pchip2d(cecp,cefp,ce2,itcp(:)',itfp(:)); # Assign the points cecp = itcp; cefp = logspace(log10(2 * cesf / fs),log10(2 * ceef / fs),cenf * fpif); # Delete unused variables clear itcp itfp; else # Remaps the frequency points for plotting cefp = logspace(log10(2 * cesf / fs),log10(2 * ceef / fs),cenf); endif # Normalize the envelope ce1 = ce1/max(ce1(:)); ce2 = ce2/max(ce2(:)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramHTRENVSD" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramHTRENVSF" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Resample the scalogram for image plotting scrf = 4; scff = 8; rcecp = linspace(cecb,cece,cenc * scrf); rcenf = scff * cenf; rce1 = pchip2d(cecp,0:(cenf-1),ce1,rcecp,linspace(0,cenf-1,rcenf)); rce2 = pchip2d(cecp,0:(cenf-1),ce2,rcecp,linspace(0,cenf-1,rcenf)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram map 1 subplot(2,1,1); imagesc(rcecp,0:(rcenf-1),rce1); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm)"); text(1.1 * cece,rcenf / 2,"Mag. (norm)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",[0.25,0.5,0.75,1.0]); colormap(EDCMap); colorbar("EastOutside"); title(it1); # Plot the scalogram map 2 subplot(2,1,2); imagesc(rcecp,0:rcenf-1,rce2); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm)"); text(1.1 * cece,rcenf / 2,"Mag. (norm)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",[0.25,0.5,0.75,1.0]); colormap(EDCMap); colorbar("EastOutside"); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramHTRENVMap" fext ],fdevice); # Convert to log scale ce1 = 20 * log10(max(ce1,10^(-30/20))); ce2 = 20 * log10(max(ce2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramHTRETCSD" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramHTRETCSF" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Resample the scalogram for image plotting scrf = 4; scff = 8; rcecp = linspace(cecb,cece,cenc * scrf); rcenf = scff * cenf; rce1 = pchip2d(cecp,0:(cenf-1),ce1,rcecp,linspace(0,cenf-1,rcenf)); rce2 = pchip2d(cecp,0:(cenf-1),ce2,rcecp,linspace(0,cenf-1,rcenf)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram map 1 subplot(2,1,1); imagesc(rcecp,0:rcenf-1,rce1); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); text(1.1 * cece,rcenf / 2,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",-25:5:5); colormap(EDCMap); colorbar("EastOutside"); title(it1); # Plot the scalogram map 2 subplot(2,1,2); imagesc(rcecp,0:rcenf-1,rce2); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); text(1.1 * cece,rcenf / 2,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",-25:5:5); colormap(EDCMap); colorbar("EastOutside"); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramHTRETCMap" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Remove variables no longer used clear cecp rcecp cefp ce1 ce2 rce1 rce2; # Report the stage disp("Morlet cycle/octave scalogram, medium time resolution..."); fflush(stdout); # Morlet cycle/octave scalogram from -10 cicles to +20 cicles # 20 Hz to 20 kHz # 100 frequency points and 350 cicle points cecb = -10; cece = 20; cenc = 350; cesf = 20; ceef = 20000; cenf = 100; # Parametri upsampling e filtro cefl = 32768; ceat = 120; ceuf = 8; cewm = 2; # Morlet wavelet ceft = 2; # Spaziatura tics asse x xtsp = 2; # Computes the cicle points cecp = linspace(cecb,cece,cenc); # Computes the frequency points cebs = 2 ^ (log2(ceef / cesf) / cenf); cefp = logspace(log10(2 * cesf / (cebs * fs)),log10(2 * ceef / (cebs * fs)),cenf); # Computes the Morlet cycle/octave scalogram ce1 = tfir(ir1, ic1, cecp, cefp, cefl, ceat, ceuf, ceft, cewm); ce2 = tfir(ir2, ic2, cecp, cefp, cefl, ceat, ceuf, ceft, cewm); # Computes the envelope for I = 1:cenf ce1(I,:) = abs(hilbert(ce1(I,:))); ce2(I,:) = abs(hilbert(ce2(I,:))); endfor # Perform the scalogram interpolation # Not effective, so disabled cpif = 1; fpif = 1; # Check if interpolation is required if (cpif > 1 || fpif > 1) # Computes the interpolation cicle points itcp = linspace(cecb,cece,cenc * cpif); # Computes the frequency points itfp = logspace(log10(2 * cesf / (cebs * fs)),log10(2 * ceef / (cebs * fs)),cenf * fpif); # Interpolates the envelope ce1 = pchip2d(cecp,cefp,ce1,itcp(:)',itfp(:)); ce2 = pchip2d(cecp,cefp,ce2,itcp(:)',itfp(:)); # Assign the points cecp = itcp; cefp = logspace(log10(2 * cesf / fs),log10(2 * ceef / fs),cenf * fpif); # Delete unused variables clear itcp itfp; else # Remaps the frequency points for plotting cefp = logspace(log10(2 * cesf / fs),log10(2 * ceef / fs),cenf); endif # Normalize the envelope ce1 = ce1/max(ce1(:)); ce2 = ce2/max(ce2(:)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramMTRENVSD" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, 0, 1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm.)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",[0.25,0.5,0.75,1.0]); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramMTRENVSF" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Resample the scalogram for image plotting scrf = 4; scff = 8; rcecp = linspace(cecb,cece,cenc * scrf); rcenf = scff * cenf; rce1 = pchip2d(cecp,0:(cenf-1),ce1,rcecp,linspace(0,cenf-1,rcenf)); rce2 = pchip2d(cecp,0:(cenf-1),ce2,rcecp,linspace(0,cenf-1,rcenf)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram map 1 subplot(2,1,1); imagesc(rcecp,0:rcenf-1,rce1); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm)"); text(1.1 * cece,rcenf / 2,"Mag. (norm)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",[0.25,0.5,0.75,1.0]); colormap(EDCMap); colorbar("EastOutSide"); title(it1); # Plot the scalogram map 2 subplot(2,1,2); imagesc(rcecp,0:rcenf-1,rce2); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (norm)"); text(1.1 * cece,rcenf / 2,"Mag. (norm)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",[0.25,0.5,0.75,1.0]); colormap(EDCMap); colorbar("EastOutSide"); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramMTRENVMap" fext ],fdevice); # Convert to log scale ce1 = 20 * log10(max(ce1,10^(-30/20))); ce2 = 20 * log10(max(ce2,10^(-30/20))); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(15, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramMTRETCSD" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram 1 subplot(2,1,1); if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce1,"edgecolor",ULColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it1); # Plot the scalogram 2 subplot(2,1,2); # Check for contour parameters if (surcntenable > 0) # Plot the surface and contour surfc(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); else # Plot the surface surf(cecp,cefp * fs / 2000,ce2,"edgecolor",LLColor,"LineWidth",EDLw); endif axis([cecb, cece, cesf / 1000, ceef / 1000, -30, 2]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); safetics("x",cecb:xtsp:cece); safetics("y",gfp,gfl); safetics("z",-25:5:5); set(gca(),"yscale","log") view(345, 45); colormap(EDCMap); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramMTRETCSF" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Resample the scalogram for image plotting scrf = 4; scff = 8; rcecp = linspace(cecb,cece,cenc * scrf); rcenf = scff * cenf; rce1 = pchip2d(cecp,0:(cenf-1),ce1,rcecp,linspace(0,cenf-1,rcenf)); rce2 = pchip2d(cecp,0:(cenf-1),ce2,rcecp,linspace(0,cenf-1,rcenf)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the scalogram map 1 subplot(2,1,1); imagesc(rcecp,0:rcenf-1,rce1); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); text(1.1 * cece,rcenf / 2,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",-25:5:5); colormap(EDCMap); colorbar("EastOutside"); title(it1); # Plot the scalogram map 2 subplot(2,1,2); imagesc(rcecp,0:rcenf-1,rce2); set(gca(),"ydir","normal"); axis([cecb, cece, 0, rcenf-1]); grid("on"); xlabel("Time (cycles)"); ylabel("Frequency (kHz)"); zlabel("Mag. (dB)"); text(1.1 * cece,rcenf / 2,"Mag. (dB)","Rotation",90,"HorizontalAlignment","center","fontsize",GDFs); safetics("x",cecb:xtsp:cece); safetics("y",(rcenf-1) * log(gfp / 0.02) / log(20 / 0.02),gfl); safetics("z",-25:5:5); colormap(EDCMap); colorbar("EastOutside"); title(it2); # Print to the output file print([ outdir fprefix "-MorletScalogramMTRETCMap" fext ],fdevice); # Reset to the standard colormap colormap("default"); # Remove variables no longer used clear cecp rcecp cefp ce1 ce2 rce1 rce2; # Report the stage disp("Completed, wait for GNUPlot to complete before opening output files."); fflush(stdout); endfunctiondrc-3.2.2/source/doc/octave/acgw.m0000644000076400001450000000311213162674023015677 0ustar denisitadm## Copyright (C) 2017 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: w = acgw(n,a) ## ## Computes an approximate Constrained Gaussian Window ## ## Reference: ## Sebatian Starosielec and Daniel Haegele ## ## Discrete-time windows with minimal RMS bandwidth ## for given RMS temporal width. ## ## Signal Processing 102, 240 (2014) ## ## n: window length ## a: alpha parameter, default 0.5 ## ## Example: ## ## w = acgw(255,5); ## function w = acgw(n,a = 2.5) c = (n - 1) / 2; m = gw(c,n,a) - gw(-0.5,n,a) * (gw(c + n,n,a) + gw(c - n,n,a)) / (gw(-0.5 + n,n,a) + gw(0.5 - n,n,a)); x = (0:(n-1))'; w = (gw(x,n,a) - gw(-0.5,n,a) * (gw(x + n,n,a) + gw(x - n,n,a)) / (gw(-0.5 + n,n,a) + gw(0.5 - n,n,a))) / m; endfunction # Internal gaussian function function w = gw(x,n,a) w = exp(-0.5 * (a * (x - (n - 1) / 2) / ((n - 1) / 2)) .^ 2); endfunctiondrc-3.2.2/source/doc/octave/cdde.m0000644000076400001450000000327611320622700015655 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: [f, hm] = cdde(n,fs) ## ## Compute an unwindowed cd deemphasis FIR filter of length n ## ## n = filter len ## fs = sample frequency ## f = filter coefficients ## hm = filter magnitude response, same length of f function [f, hm] = cdde(n,fs) # Calcola le frequenze di interpolazione f = linspace(0,fs/2,n); # Calcola le componenti per il calcolo della risposta in ampiezza # Costanti di tempo 0.5 uS e 0.15 uS l = 2 * pi * 0.00005 * f(2:n); h = 2 * pi * 0.000015 * f(2:n); b = 1 + 1 ./ (l .* l); a = 1 + 1 ./ (h .* h); # Calcola la risposta in ampiezza hm = [ 1 (((0.09 * a) ./ b) .^ 0.5) ]; # Prepara l'array per il calcolo della risposta temporale if (fix(n/2) == n/2) hm2 = [ hm hm(n:-1:1) ]; else hm2 = [ hm hm((n-1):-1:1) ]; endif # Estrae la risposta del filtro a fase minima [a, f] = rceps(real(ifft(hm2))); # Estrae la parte rilevante f = f(1:n); endfunctiondrc-3.2.2/source/doc/octave/pchip2d.m0000644000076400001450000000211111320622700016272 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: ZI = pchip2d(X,Y,Z,XI,YI) ## ## Bidimensional pchip interpolation ## ## Return a matrix ZI corresponding to the pchip interpolations at ## XI and YI of the data supplied as X, Y and Z. ## function ZI = pchip2d(X,Y,Z,XI,YI) ZI = pchip(Y,pchip(X,Z,XI)',YI)'; endfunctiondrc-3.2.2/source/doc/octave/XOver.txt0000644000076400001450000000642512260560004016405 0ustar denisitadmls = loadpcm('S:\Room\1038B-2013-12-28-XOTest\2\lsub.pcm'); lm = loadpcm('S:\Room\1038B-2013-12-28-XOTest\2\lmain.pcm'); rs = loadpcm('S:\Room\1038B-2013-12-28-XOTest\2\rsub.pcm'); rm = loadpcm('S:\Room\1038B-2013-12-28-XOTest\2\rmain.pcm'); [mv, mi ] = max(abs(lm)); ls = ls((mi-2048):(mi+2^17)); lm = lm((mi-2048):(mi+2^17)); rs = rs((mi-2048):(mi+2^17)); rm = rm((mi-2048):(mi+2^17)); in = length(ls); dc = [ zeros(2048,1); 1; zeros(2^17,1) ]; # Linear phase sd = 0; sf = 25; md = 160; mf = 65; mg = 1; sg = 4; so = 0; mo = 0; sl = 4095; ml = 4095; sa = 300; ma = 300; semilogx(linspace(0.001,22050,in/2),20 * log10([abs(fft(xosim(44100,ls,sg,sd,sf,sl,sa,so,lm,mg,md,mf,ml,ma,mo))(1:(in/2))),abs(fft(xosim(44100,rs,sg,sd,sf,sl,sa,so,rm,mg,md,mf,ml,ma,mo))(1:(in/2))),abs(fft(xosim(44100,dc,sg,sd,sf,sl,sa,so,dc,mg,md,mf,ml,ma,mo))(1:(in/2))),abs(fft(xosim(44100,dc,0,sd,sf,sl,sa,so,dc,mg,md,mf,ml,ma,mo))(1:(in/2))),abs(fft(xosim(44100,dc,sg,sd,sf,sl,sa,so,dc,0,md,mf,ml,ma,mo))(1:(in/2)))]));grid("on");axis([10 1000 -90 10]); tics("x",logspace(1,3,15),num2str(logspace(1,3,15),"%.1f\n")) sd = 0; sf = 25; md = 160; mf = 65; mg = 1; sg = 4; so = 0; mo = 0; sl = 4095; ml = 4095; sa = 300; ma = 300; semilogx(linspace(0.001,22050,in/2),20 * log10([abs(fft(xosim(44100,dc,sg,sd,sf,sl,sa,so,dc,mg,md,mf,ml,ma,mo))(1:(in/2))),abs(fft(xosim(44100,dc,0,sd,sf,sl,sa,so,dc,mg,md,mf,ml,ma,mo))(1:(in/2))),abs(fft(xosim(44100,dc,sg,sd,sf,sl,sa,so,dc,0,md,mf,ml,ma,mo))(1:(in/2)))]));grid("on");axis([10 1000 -90 10]); tics("x",logspace(1,3,15),num2str(logspace(1,3,15),"%.1f\n")) savepcm(lfxosim(44100,ls,sg,sd,sf,sl,sa,so,lm,mg,md,mf,ml,ma,mo),'S:\Room\1038B-2013-12-28-XOTest\lsim.pcm'); savepcm(lfxosim(44100,rs,sg,sd,sf,sl,sa,so,rm,mg,md,mf,ml,ma,mo),'S:\Room\1038B-2013-12-28-XOTest\rsim.pcm'); # Definitivo sd = 0; sf = 25; md = 160; mf = 65; mg = 1; sg = 4; so = 0; mo = 0; sl = 4095; ml = 4095; sa = 300; ma = 300; [lp, hp] = mklfxo(44100,sg,sd,sf,sl,sa,so,mg,md,mf,ml,ma,mo); savepcm(postpad(lp,8192),'S:\Room\1038B-2013-12-28-XOTest\lp.pcm'); savepcm(postpad(hp,8192),'S:\Room\1038B-2013-12-28-XOTest\hp.pcm'); # Minimum phase sd = 0; sf = 25; md = 0; mf = 80; mg = 1; sg = -4; so = 2; mo = 2; sl = 8191; ml = 8191; fa = 0; semilogx(linspace(0.001,22050,in/2),20 * log10([abs(fft(lrxosim(44100,ls,sg,sd,sf,so,sl,fa,lm,mg,md,mf,mo,ml,fa))(1:(in/2))),abs(fft(lrxosim(44100,rs,sg,sd,sf,so,sl,fa,rm,mg,md,mf,mo,ml,fa))(1:(in/2))),abs(fft(lrxosim(44100,dc,0,sd,sf,so,sl,fa,dc,mg,md,mf,mo,ml,fa))(1:(in/2))),abs(fft(lrxosim(44100,dc,sg,sd,sf,so,sl,fa,dc,0,md,mf,mo,ml,fa))(1:(in/2))),abs(fft(lrxosim(44100,dc,sg,sd,sf,so,sl,fa,dc,mg,md,mf,mo,ml,fa))(1:(in/2)))]));grid("on");axis([10 1000 -90 10]); tics("x",logspace(1,3,15),num2str(logspace(1,3,15),"%.1f\n")) savepcm(lrxosim(44100,ls,sg,sd,sf,so,sl,fa,lm,mg,md,mf,mo,ml,fa),'S:\Room\1038B-2013-12-28-XOTest\lsim.pcm'); savepcm(lrxosim(44100,rs,sg,sd,sf,so,sl,fa,rm,mg,md,mf,mo,ml,fa),'S:\Room\1038B-2013-12-28-XOTest\rsim.pcm'); # Definitivo sd = 0; sf = 25; md = 0; mf = 80; mg = 1; sg = -4; so = 2; mo = 2; sl = 8191; ml = 8191; fa = 0; [lp, hp] = mklrxo(44100,sg,sd,sf,so,sl,fa,mg,md,mf,mo,ml,fa); savepcm(postpad(lp,8192),'S:\Room\1038B-2013-12-28-XOTest\lp.pcm'); savepcm(postpad(hp,8192),'S:\Room\1038B-2013-12-28-XOTest\hp.pcm');drc-3.2.2/source/doc/octave/createbasicplots.m0000644000076400001450000002746713163170154020325 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: createbasicplots(ptfname,outdir,fprefix); ## ## createbasicplots - Creates the basic DRC plots ## ## ptfname = psychoacoustic target sample response file name ## outdir = output directory for eps files ## fprefix = prefix for eps files function createbasicplots(ptfname,outdir,fprefix); # Set the frequency dependent windowing basic parameters sf = 20; sw = 500; ef = 20000; ew = 0.5; np = 31768; ptw = 0.3; # 300 ms, psychoacoustic window dlw = 1.5; # Default line width # Default font sizes GDFs = 8; # Creates the windows array wa = linspace(ew,sw,np); # Computes the gabor limit gl = 1000 ./ (2 * linspace(ew/4,sw,np)); # Report the stage disp("Frequency dependent windowing, linear scale..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Set default font size set(0,"defaultaxesfontsize",GDFs) # Plot the frequency dependent windowing curves for gn = 1:10 plot(wa,fslprefilt(sf,sw,ef,ew,0.2 * gn,np),sprintf(";WE = %.1f;",0.2 * gn),"color",hsv2rgb([0.9 * (gn - 1) / 9, 1, 0.75]),"LineWidth",dlw); hold("on"); endfor hold("off"); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (Hz)"); axis([0.3, 550, 10, 21000]); safetics("x",0:50:550); safetics("y",0:1000:21000); # Print to the output file print([ outdir fprefix "-Linear.eps" ],"-depsc2"); # Report the stage disp("Frequency dependent windowing, semilogy scale..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the frequency dependent windowing curves for gn = 1:10 semilogy(wa,fslprefilt(sf,sw,ef,ew,0.2 * gn,np),sprintf(";WE = %.1f;",0.2 * gn),"color",hsv2rgb([0.9 * (gn - 1) / 9, 1, 0.75]),"LineWidth",dlw); hold("on"); endfor hold("off"); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (Hz)"); axis([0.3, 550, 10, 21000]); safetics("x",0:50:550); safetics("y",[10,20,30,50,100,200,300,500,1000,2000,3000,5000,10000,20000]); # Print to the output file print([ outdir fprefix "-SemiLogY.eps" ],"-depsc2"); # Report the stage disp("Frequency dependent windowing, semilogx scale..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the frequency dependent windowing curves for gn = 1:10 semilogx(wa,fslprefilt(sf,sw,ef,ew,0.2 * gn,np),sprintf(";WE = %.1f;",0.2 * gn),"color",hsv2rgb([0.9 * (gn - 1) / 9, 1, 0.75]),"LineWidth",dlw); hold("on"); endfor hold("off"); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (Hz)"); axis([0.3, 550, 10, 21000]); safetics("x",[0.3,0.5,1,2,3,5,10,20,30,50,100,200,300,500]); safetics("y",0:1000:21000); # Print to the output file print([ outdir fprefix "-SemiLogX.eps" ],"-depsc2"); # Report the stage disp("Frequency dependent windowing, loglog scale..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the frequency dependent windowing curves for gn = 1:10 loglog(wa,fslprefilt(sf,sw,ef,ew,0.2 * gn,np),sprintf(";WE = %.1f;",0.2 * gn),"color",hsv2rgb([0.9 * (gn - 1) / 9, 1, 0.75]),"LineWidth",dlw); hold("on"); endfor hold("off"); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (Hz)"); axis([0.3, 550, 10, 21000]); safetics("x",[0.3,0.5,1,2,3,5,10,20,30,50,100,200,300,500]); safetics("y",[10,20,30,50,100,200,300,500,1000,2000,3000,5000,10000,20000]); # Print to the output file print([ outdir fprefix "-LogLog.eps" ],"-depsc2"); # Report the stage disp("Frequency dependent windowing, loglog scale with gabor limit..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the frequency dependent windowing curves for gn = 1:10 loglog(wa,fslprefilt(sf,sw,ef,ew,0.2 * gn,np),sprintf(";WE = %.1f;",0.2 * gn),"color",hsv2rgb([0.9 * (gn - 1) / 9, 1, 0.75]),"LineWidth",dlw); hold("on"); endfor loglog(linspace(ew/4,sw,np),gl,";Gabor;","color",[0.5,0.5,0.5],"LineWidth",dlw); hold("off"); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (Hz)"); axis([0.3, 550, 10, 21000]); safetics("x",[0.3,0.5,1,2,3,5,10,20,30,50,100,200,300,500]); safetics("y",[10,20,30,50,100,200,300,500,1000,2000,3000,5000,10000,20000]); # Print to the output file print([ outdir fprefix "-Gabor.eps" ],"-depsc2"); # Report the stage disp("Frequency dependent windowing, time-frequency jail..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the frequency dependent windowing curves semilogy(-wa/20,fslprefilt(sf,sw/20,ef,ew,1.0,np),"1;Pre-echo truncation;","LineWidth",dlw); hold("on"); semilogy(wa,fslprefilt(sf,sw,ef,ew,1.0,np),"3;Ringing truncation;","LineWidth",dlw); hold("off"); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (Hz)"); axis([-50, 550, 10, 21000]); safetics("x",-50:50:550); safetics("y",[10,20,30,50,100,200,300,500,1000,2000,3000,5000,10000,20000]); # Print to the output file print([ outdir fprefix "-Jail.eps" ],"-depsc2"); # Report the stage disp("Frequency dependent windowing, psychoacoustic bandwidth comparison..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the frequency dependent windowing curves loglog(linspace(sf,ef,np)/1000,(1000 * 0.5) ./ (wslprefilt(sf,sw,ef,ew,1.0,np) + wslprefilt(sf,sw/20,ef,ew,1.0,np)),"1;normal.drc;","LineWidth",dlw); hold("on"); loglog(linspace(sf,ef,np)/1000,(1000 * 2.0) ./ (wbslprefilt(sf,65,ef,0.46,1.87,np) + wbslprefilt(sf,10,ef,0.46,1.87,np)),"2;erb.drc;","LineWidth",dlw); hold("on"); loglog(linspace(sf,ef,np)/1000,barkbwidth(linspace(sf,ef,np)),"3;Bark;","LineWidth",dlw); hold("on"); loglog(linspace(sf,ef,np)/1000,erbbwidth(linspace(sf,ef,np)),"4;ERB;","LineWidth",dlw); hold("on"); loglog(linspace(sf,ef,np)/1000,foctbwidth(linspace(sf,ef,np),1/3),"5;1-3 oct;","LineWidth",dlw); hold("on"); loglog(linspace(sf,ef,np)/1000,foctbwidth(linspace(sf,ef,np),1/6),"0;1-6 oct;","LineWidth",dlw); hold("off"); grid("on"); xlabel("Frequency (kHz)"); ylabel("Frequency (Hz)"); axis([0.01, 21, 0.5, 10000]); safetics("x",[0.01,0.02,0.03,0.05,0.1,0.2,0.3,0.5,1,2,3,5,10,20]); safetics("y",[0.5,1,2,3,5,10,20,30,50,100,200,300,500,1000,2000,3000,5000,10000]); legend("location","northwest"); # Print to the output file print([ outdir fprefix "-BWidthCmp.eps" ],"-depsc2"); # Report the stage disp("Frequency dependent windowing, proportional and bilinear comparison..."); fflush(stdout); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the frequency dependent windowing curves for gn = 1:7 loglog(wa,fslprefilt(sf,sw,ef,ew,0.2 + 0.2 * gn,np),sprintf(";Prop. WE = %.1f;",0.2 + 0.2 * gn),"color",hsv2rgb([0.9 * (gn - 1) / 7, 1, 0.75]),"LineWidth",dlw); hold("on"); endfor for gn = 1:7 loglog(wa,fbslprefilt(sf,sw,ef,ew,0.2 + 0.2 * gn,np),sprintf(";Bil. WE = %.1f;",0.2 + 0.2 * gn),"color",hsv2rgb([0.9 * (gn - 1) / 7, 1, 0.50]),"LineWidth",dlw); hold("on"); endfor hold("off"); grid("on"); xlabel("Time (ms)"); ylabel("Frequency (Hz)"); axis([0.3, 550, 10, 21000]); safetics("x",[0.3,0.5,1,2,3,5,10,20,30,50,100,200,300,500]); safetics("y",[10,20,30,50,100,200,300,500,1000,2000,3000,5000,10000,20000]); # Print to the output file print([ outdir fprefix "-BPComparison.eps" ],"-depsc2"); # Report the stage disp("Transfer functions..."); fflush(stdout); # Prepare the target functions bkf = [ 0.01 10 20 400 12800 20000 21500 22050 ]; bkm = [ -20.0 -10.0 0.00 0.00 -5.00 -6.00 -10.0 -20.0 ]; bk2f = [ 0.01 10 20 200 12800 20000 21500 22050 ]; bk2m = [ -20.0 -10.0 0.00 0.00 -3.0 -3.5 -10.0 -20.0 ]; bk2sf = [ 0.01 16 18 200 12800 20000 21500 22050 ]; bk2sm = [ -200.0 -120.0 0.00 0.00 -3.0 -3.5 -10.0 -20.0 ]; bk3f = [ 0.01 10 20 100 12800 20000 21500 22050 ]; bk3m = [ -20.0 -10.0 0.00 0.00 -3.50 -4.00 -10.0 -20.0 ]; bk3sf = [ 0.01 16 18 100 12800 20000 21500 22050 ]; bk3sm = [ -200.0 -120.0 0.00 0.00 -3.50 -4.00 -10.0 -20.0 ]; bk3sfsp = [ 0.01 14 15 16 17 18 19 20 50 100 150 19900 20000 20100 20200 20300 20400 20500 22050 ]; bk3smsp = [ -200.0 -200.0 -200.0 -200.0 -100.0 0.00 0.00 0.00 0.00 0.00 0.00 -3.95 -4.00 -4.00 -98.0 -200.0 -200.0 -200.0 -200.0 ]; # Plot the target functions semilogx(bkf/1000,bkm,"1;bk;","LineWidth",dlw); hold("on"); semilogx(bk2f/1000,bk2m,"2;bk-2;","LineWidth",dlw); hold("on"); semilogx(bk3f/1000,bk3m,"5;bk-3;","LineWidth",dlw); hold("on"); semilogx(bk2sf/1000,bk2sm,"4;bk-2-sub;","LineWidth",dlw); hold("on"); semilogx(bk3sf/1000,bk3sm,"3;bk-3-sub;","LineWidth",dlw); hold("on"); lbk3sfsp = log10(0.01 + bk3sfsp); spx = log10(logspace(log10(0.01),log10(22050.01),np)); semilogx((10 .^ ub3splinev(lbk3sfsp,lbk3sfsp,spx)) / 1000, -6 + ub3splinev(lbk3sfsp,bk3smsp,spx),";bk-3-subultra-spline (-6 dB);","color",[0.5, 0.5, 0.5],"LineWidth",dlw); hold("on"); semilogx(logspace(log10(0.01),log10(22050.01),np) / 1000, -9 + interp1(log10(0.01 + bk3sf),bk3sm,spx,'pchip'), "0;bk-3-sub-pchip (-9 dB);","LineWidth",dlw); clear spx lbk3sfsp; hold("off"); grid("on"); xlabel("Frequency (kHz)"); ylabel("Frequency (Hz)"); axis([0.01, 22.05, -30, 9]); safetics("x",[0.01,0.02,0.03,0.05,0.1,0.2,0.3,0.5,1,2,3,5,10,20]); safetics("y",-30:3:9); legend("location","south"); # Print to the output file print([ outdir fprefix "-DTFCmp.eps" ],"-depsc2"); # Remove variables no longer used clear sf sw ef ew wa gl; # Report the stage disp("Spectral envelope and standard smoothing comparison..."); fflush(stdout); # Calcola la finestratura ptwl = round(ptw * 44100); # Carica il file campione ptr = loadpcm(ptfname); # Trova la posizione del picco [ptm, pti] = max(abs(ptr)); # Effettua la finestratura ptr = (ptr((pti-(ptwl-1)):(pti+ptwl)) .* blackman(2 * ptwl)); # Normalizza il file ptr = ptr / norm(ptr); # Calcola l'inviluppo spettrale ptev = 20 * log10(ssev(ptr,44100,-2,15)); # Calcola lo spettro unsmoothed ptus = 20 * log10(abs(fft(postpad(ptr,2 * length(ptev)))(1:length(ptev)))); # Calcola lo smoothing standard ptss = 20 * log10(ssev(ptr,44100,-2,1)); # Calcola l'array risposta in frequenza ptf = linspace(0.0001,22050,length(ptev)); # Calcola il punto di riferimento in frequenza ptfp = round(100 * 22050 / length(ptf)); # Open a new plot newplot(); clf(); figure(1,"visible","off"); # Plot the spectral envelope example semilogx(ptf/1000,ptus,"1;Unsmoothed;","LineWidth",dlw); hold("on"); semilogx(ptf/1000,ptss,"0;ERB smoothed;","LineWidth",dlw); hold("on"); semilogx(ptf/1000,ptev,"3;ERB spectral envelope;","LineWidth",dlw); hold("on"); semilogx([20 100 20000] / 1000,[0 0 log2(20000 / 100)] + ptev(ptfp),"5;Reference target;","LineWidth",dlw); hold("off"); grid("on"); xlabel("Frequency (kHz)"); ylabel("Magnitude (dB)"); axis([0.02, 20, -35, 25]); safetics("x",[0.02,0.03,0.05,0.1,0.2,0.3,0.5,1,2,3,5,10,20]); safetics("y",-35:5:25); # Print to the output file print([ outdir fprefix "-SpectralEnvelope.eps" ],"-depsc2"); # Remove variables no longer used clear ptf ptr ptev ptus ptss; # Report the stage disp("Completed, wait for GNUPlot to complete before opening output files."); fflush(stdout); endfunctiondrc-3.2.2/source/doc/octave/sintable.m0000644000076400001450000000246511320622700016556 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: st = sintable(sv,sd,sn) ## ## Generate a sin table by recurrence ## ## sv: sine start value ## sd: sine delta ## sn: sine number of values function st = sintable(sv,sd,sn); # Initializes the sin array st = zeros(1,sn); # Initializes the sine constants R = sin(sd/2); R = -4 * R * R; S = sin(sv); S = sin(sd) * cos(sv) + (S * (1 - cos(sd))); # Set the first value V = sin(sv); st(1) = V; # Sine generation loop for I = 2:sn S = R * V + S; V = V + S; st(I) = V; endfor endfunctiondrc-3.2.2/source/doc/octave/tfir.m0000644000076400001450000001113313162674651015733 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: tf = tfir(is, ic, cp, fp, fl, at, uf, ft, wm) ## ## Time-frequency impulse response ## ## is: input signal ## is: input signal center ## cp: time axis cicles points ## fp: filtering frequency points ## fl: filter length used for ETC filtering ## at: filter stopband attenuation, negative use blackman ## uf: integer upsampling factor for internal computation ## ft: filter type, 0 = lowpass, 1 = bandpass, 2 = morlet, 3 = constrained gaussian ## wm: wavelet frequency multiplier for Morlet wavelet, usually 2, ## alpha parameter for constrained gausssian, default 2.5 function tf = tfir(is, ic, cp, fp, fl, at, uf, ft, wm); # Extracts the minimum frequency point mfp = min(fp); # Computes the upsampling range ib = ic + floor(2 * min(cp) / mfp); ie = ic + ceil(2 * max(cp) / mfp); # Rescales the input signal is = is(ib:ie); ic = ic - ib; # Makes the upsampling factor an integer uf = round(uf); # Rescales the filter length fl = fl * uf; # Perform the initial upsampling if (uf > 1) ul = length(is) * uf; us = zeros(ul,1); us(1:uf:ul) = is; else ul = length(is); us = is(:); endif # Allocates the cumulative IR output matrix nf = length(fp); nc = length(cp); tf = zeros(nf,nc); # Check if morlet if (ft == 2) # Compute the sampling frequency needed to get the # desired base wavelet frequency wf = (wm * uf) / mfp; # Computes the wavelet length needed to get the desired # base filter length wl = (fl - 1) / (2 * wf); endif # Add the last frequency point if missing if (fp(nf) < 1.0) fp = [fp 1.0]; else # Decrease the number of points nf = nf - 1; endif # Cumulative IR computation loop for I = 1:nf # Check the filter type if (ft == 0) # Computes the filter center frequency ff = sqrt(fp(I) * fp(I + 1)); # Computes the effective filter len efl = round(fl * mfp / ff); # Lowpass if (at < 0) ifir = lowpassfir(efl,ff/uf)' .* blackman(efl); else ifir = lowpassfir(efl,ff/uf)' .* chebwin(efl,at); endif # Computes the compensation factor cf = ff; elseif (ft == 1) # Computes the filter center frequency ff = sqrt(fp(I) * fp(I + 1)); # Computes the effective filter len efl = round(fl * mfp / ff); # Bandpass if (at < 0) ifir = bandpassfir(efl,fp(I)/uf,fp(I + 1)/uf)' .* blackman(efl); else ifir = bandpassfir(efl,fp(I)/uf,fp(I + 1)/uf)' .* chebwin(efl,at); endif # Computes the compensation factor cf = fp(I + 1) - fp(I); elseif (ft == 2) # Computes the filter center frequency ff = sqrt(fp(I) * fp(I + 1)); # Morlet ifir = morletw(wf,mfp / ff,0,wl,1,wm * pi); # Estract the filter len efl = length(ifir); # Computes the compensation factor cf = ff ^ 0.5; elseif (ft == 3) # Computes the filter center frequency ff = sqrt(fp(I) * fp(I + 1)); # Computes the effective filter len efl = round(fl * mfp / ff); # Constrained gaussian sine ifir = sin(2 * pi * ff * (0:(efl - 1)) / efl)' .* acgw(efl,wm); # Computes the compensation factor cf = ff; else # Computes the filter center frequency ff = sqrt(fp(I) * fp(I + 1)); # Computes the effective filter len efl = round(fl * mfp / ff); # Lowpass if (at < 0) ifir = lowpassfir(efl,ff/uf)' .* blackman(efl); else ifir = lowpassfir(efl,ff/uf)' .* chebwin(efl,at); endif # Computes the compensation factor cf = ff; endif # Applies the filter if (efl > 1) ec = real(fftconv(ifir,us)); else ec = us; endif # Computes the filter delay fd = (efl) / 2; # Computes the references el = ul + efl - 1; uc = (ic * uf) + fd; # Computes the cicle rescaling cs = (-uc * ff) / (2 * uf); ce = ((el - uc) * ff) / (2 * uf); # Interpolate at the requested cycle points tf(I,:) = interp1(linspace(cs,ce,el), ec, cp, '*pchip') / cf; endfor endfunctiondrc-3.2.2/source/doc/octave/ptics.m0000644000076400001450000000276112724244053016110 0ustar denisitadm## Copyright (C) 2002 Paul Kienzle ## Copyright (C) 2005 Dmitri A. Sergatskov ## Copyright (C) 2007 Russel Valentine ## Copyright (C) 2007 Peter Gustafson ## This program is in the public domain ## -*- texinfo -*- ## @deftypefn {Function File} {} ptics (@var{axis}, [@var{pos1}, @var{pos2}, @dots{}], [@var{lab1}, @var{lab2}, @dots{}],) ## Explicitly set the tic positions and labels for the given axis. ## ## @var{axis} must be 'x', 'y' or 'z'. ## ## If no positions or labels are given, then restore the default. ## If positions are given but no labels, use those positions with the ## normal labels. If positions and labels are given, each position ## labeled with the corresponding row from the label matrix. ## ## @end deftypefn function ptics (axis, pos, lab) if ( nargin < 1 || nargin > 3 ) print_usage; endif t = lower (axis); if (t ~= "x" && t ~= "y" && t ~= "z") error ("First input argument must be one of 'x', 'y' or 'z'"); endif if (nargin == 1) set (gca(), [t, "tick"], []); set (gca(), [t, "tickmode"], "auto"); set (gca(), [t, "ticklabel"], ""); set (gca(), [t, "ticklabelmode"], "auto"); elseif (nargin == 2) set (gca(), [t, "tick"], pos); set (gca(), [t, "ticklabel"], ""); set (gca(), [t, "ticklabelmode"], "auto"); elseif (nargin == 3) set (gca(), [t, "tick"], pos); set (gca(), [t, "ticklabel"], lab); else ## we should never get here anyway print_usage; endif endfunction drc-3.2.2/source/doc/octave/barkwarp.m0000644000076400001450000000306611320622700016564 0ustar denisitadmfunction lambda = barkwarp(fs) #BARKWARP - Computation of warping coefficient # # lambda = barkwarp(fs) # # computes an optimal warping coefficient vs sample rate in Hertz # to approximate the psychoacoustic Bark scale # approximation by J.O. Smith and J.S. Abel (1995) # # If output argument is not specified, e.g., # >> barkwarp(44100) # the function plots the warping function and shows the optimal # coefficient value on the title line of the figure. # The turning point frequency, i.e., # the frequency below which the frequency resolution of the # system is higher than in a non-warped system, is also shown in # the figure as a vertical line. # # This function is a part of WarpTB - a Matlab toolbox for # warped signal processing (http://www.acoustics.hut.fi/software/warp/). # See 'help WarpTB' for related functions and examples # Authors: Matti Karjalainen, Aki Hrm # Helsinki University of Technology, Laboratory of Acoustics and # Audio Signal Processing # Adapted to Octave by Denis Sbragion # (Smith&Abel, 1995) # lambda = 1.0211*sqrt((2/pi)*atan(0.000076*fs))-0.19877; # (Smith&Abel, 1999) Is there an error in formula (26)? lambda = 1.0674*sqrt((2/pi)*atan(0.06583*fs/1000))-0.1916; if nargout==0, F=freqz([-lambda 1],[1 -lambda]); a=-angle(F); tp=fs/(2*pi)*atan(sqrt(lambda^(-2)-1)); grid __gnuplot_raw__("set xlabel \"Frequency [kHz]\"\n"); __gnuplot_raw__("set ylabel \"Normalized warped frequency\"\n"); axis([0 fs/2000 0 1]); plot(linspace(0,fs/2000,512),a/pi,sprintf(";Bark warping function for lambda = %f;", lambda)); end endfunction drc-3.2.2/source/doc/octave/foctbwidth.m0000644000076400001450000000223611320622700017106 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: bw = foctbwidth(fp,of) ## ## Computes the fractional octave bandwiddth for ## an array of frequency points ## ## fp = frequency points array ## of = octave fraction function bw = foctbwidth(fp,of) if (nargin != 2) usage("bw = foctbwidth(fp,of)"); endif # Computes the bandwidths bw = (fp * (2 ^ (0.5 * of))) - (fp * (2 ^ (-0.5 * of))); endfunctiondrc-3.2.2/source/doc/octave/mkxo.m0000644000076400001450000000774312260560746015756 0ustar denisitadm## Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: [lp, hp] = mkxo(fs,lpl,lpd,lpf,lpn,lpt,lpo,hpl,hpd,hpf,hpn,hpt,hpo) ## ## Makes a FIR xover pair ## ## fs: sample rate ## lpl: lowpass level ## lpd: lowpass delay ## lpf: lowpass xover frequency ## lpn: lowpass xover filter length ## lpt: lowpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## lpo: lowpass xover half order, 0 use a linear phase brickwall, ## negative use a minimum phase brickwall. ## hpl: highpass level ## hpd: highpass delay ## hpf: highpass xover frequency ## hpn: highpass xover filter length ## hpt: highpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## hpo: highpass xover half order, 0 use a linear phase brickwall, ## negative use a minimum phase brickwall. ## ## Example: ## ## [lp, hp] = mkxo(44100,1,0,80,4096,0,0,1,0,80,4096,0,0); ## function [lp, hp] = mkxo(fs,lpl,lpd,lpf,lpn,lpt,lpo,hpl,hpd,hpf,hpn,hpt,hpo) # Compute the filter centers if (lpo == 0) lpc = (lpn + 1) / 2; else lpc = 0; endif if (hpo == 0) hpc = (hpn + 1) / 2; else hpc = 0; endif # Computes the alignement delays if (lpc > hpc) lps = 0; hps = round(abs(lpc - hpc)); else lps = round(abs(lpc - hpc)); hps = 0; endif # Computes the low pass filter if (lpo > 0) # LR24 filter [lpb, lpa] = butter(lpo,2 * lpf / fs); if (lpt == 0) lp = lpl * prepad(filter(lpb,lpa,filter(lpb,lpa,[ 1; zeros(lpn - 1,1) ])) .* flipud(blackman(2 * lpn)(1:lpn)),lps + lpd + lpn); else lp = lpl * prepad(filter(lpb,lpa,filter(lpb,lpa,[ 1; zeros(lpn - 1,1) ])) .* flipud(chebwin(2 * lpn,lpt)(1:lpn)),lps + lpd + lpn); endif else if (lpo < 0) # Minimum phase filter if (lpt == 0) lp = bandpassfir(lpn,0,2 * lpf / fs)' .* blackman(lpn); else lp = bandpassfir(lpn,0,2 * lpf / fs)' .* chebwin(lpn,lpt); endif lp = hdmp(postpad(lp,32 * lpn))(1:lpn); lp = lpl * prepad(lp .* flipud(blackman(2 * lpn)(1:lpn)),lps + lpd + lpn); else # Linear phase filter if (lpt == 0) lp = lpl * prepad(bandpassfir(lpn,0,2 * lpf / fs)' .* blackman(lpn),lps + lpd + lpn); else lp = lpl * prepad(bandpassfir(lpn,0,2 * lpf / fs)' .* chebwin(lpn,lpt),lps + lpd + lpn); endif endif endif # Computes the high pass filter if (hpo > 0) # LR24 filter [hpb, hpa] = butter(hpo,2 * hpf / fs,'high'); if (hpt == 0) hp = hpl * prepad(filter(hpb,hpa,filter(hpb,hpa,[ 1; zeros(hpn - 1,1) ])) .* flipud(blackman(2 * hpn)(1:hpn)),hps + hpd + hpn); else hp = hpl * prepad(filter(hpb,hpa,filter(hpb,hpa,[ 1; zeros(hpn - 1,1) ])) .* flipud(chebwin(2 * hpn,hpt)(1:hpn)),hps + hpd + hpn); endif else if (hpo < 0) # Minimum phase filter if (hpt == 0) hp = bandpassfir(hpn,2 * hpf / fs,1)' .* blackman(hpn); else hp = bandpassfir(hpn,2 * hpf / fs,1)' .* chebwin(hpn,hpt); endif hp = hdmp(postpad(hp,32 * hpn))(1:hpn); hp = hpl * prepad(hp .* flipud(blackman(2 * hpn)(1:hpn)),hps + hpd + hpn); else # Linear phase filter if (hpt == 0) hp = hpl * prepad(bandpassfir(hpn,2 * hpf / fs,1)' .* blackman(hpn),hps + hpd + hpn); else hp = hpl * prepad(bandpassfir(hpn,2 * hpf / fs,1)' .* chebwin(hpn,hpt),hps + hpd + hpn); endif endif endif endfunctiondrc-3.2.2/source/doc/octave/erbwarp.m0000644000076400001450000000271211320622700016412 0ustar denisitadmfunction lambda = erbwarp(fs) #ERBWARP - Computation of warping coefficient # # lambda = erbwarp(fs) # # computes an optimal warping coefficient vs sample rate in Hertz # to approximate the psychoacoustic Erb scale # approximation by J.O. Smith and J.S. Abel (1995) # # If output argument is not specified, e.g., # >> barkwarp(44100) # the function plots the warping function and shows the optimal # coefficient value on the title line of the figure. # The turning point frequency, i.e., # the frequency below which the frequency resolution of the # system is higher than in a non-warped system, is also shown in # the figure as a vertical line. # # This function is a part of WarpTB - a Matlab toolbox for # warped signal processing (http://www.acoustics.hut.fi/software/warp/). # See 'help WarpTB' for related functions and examples # Authors: Matti Karjalainen, Aki Hrm # Helsinki University of Technology, Laboratory of Acoustics and # Audio Signal Processing # Adapted to Octave by Denis Sbragion # (Smith&Abel, 1999) Formula (30) lambda = 0.7446*sqrt((2/pi)*atan(0.1418*fs/1000))+0.03237; if nargout==0, F=freqz([-lambda 1],[1 -lambda]); a=-angle(F); tp=fs/(2*pi)*atan(sqrt(lambda^(-2)-1)); grid __gnuplot_raw__("set xlabel \"Frequency [kHz]\"\n"); __gnuplot_raw__("set ylabel \"Normalized warped frequency\"\n"); axis([0 fs/2000 0 1]); plot(linspace(0,fs/2000,512),a/pi,sprintf(";ERB warping function for lambda = %f;", lambda)); end endfunction drc-3.2.2/source/doc/octave/mklfxo.m0000644000076400001450000000411211320622700016244 0ustar denisitadm## Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: [lp, hp] = mklfxo(fs,lpd,lpf,lpn,lpt,lpl,hpd,hpf,hpn,hpt,hpl) ## ## Makes a linear phase FIR xover pair ## ## fs: sample rate ## lpd: lowpass delay ## lpf: lowpass xover frequency ## lpn: lowpass xover filter length ## lpt: lowpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## lpl: lowpass lower frequency, usually 0 ## hpd: highpass delay ## hpf: highpass xover frequency ## hpo: highpass xover half order ## hpn: highpass xover filter length ## hpt: highpass xover filter Dolph window stopband attenuation, ## 0 = use Blackman window ## hpl: highpass upper frequency, usually fs / 2 ## ## Example: ## ## [lp, hp] = mklfxo(44100,0,80,4096,0,0,0,80,4096,0,22050); ## function [lp, hp] = mklfxo(fs,lpd,lpf,lpn,lpt,lpl,hpd,hpf,hpn,hpt,hpl) # Computes the low pass filter if (lpt == 0) lp = prepad(bandpassfir(lpn - lpd,2 * lpl / fs,2 * lpf / fs) .* blackman(lpn - lpd)',lpn); else lp = prepad(bandpassfir(lpn - lpd,2 * lpl / fs,2 * lpf / fs) .* chebwin(lpn - lpd,lpt)',lpn); endif # Computes the high pass filter if (hpt == 0) hp = prepad(bandpassfir(hpn - hpd,2 * hpf / fs,2 * hpl / fs) .* blackman(hpn - hpd)',lpn); else hp = prepad(bandpassfir(hpn - hpd,2 * hpf / fs,2 * hpl / fs) .* chebwin(hpn - hpd,hpt)',lpn); endif endfunctiondrc-3.2.2/source/doc/octave/oct3bands.m0000644000076400001450000000251011320622700016624 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: [ cf, fb ] = oct3bands() ## ## Returns the center frequency and the frequency ## bounds for standard 1/3 of octave bands ## function [ cf, fb ] = oct3bands() # Assign the center frequencies # extended by one band cf = [16 20 25 31.5 40 50 63 80 100 125 160 200 250 315 400 500 630 800 1000 1250 1600 2000 2500 3150 4000 5000 6300 8000 10000 12500 16000 20000 25000]; # Computes the frequency bounds fb = (cf(1:(end-1)) .* cf(2:(end))) .^ 0.5; # Remove the unused center frequencies cf = cf(2:(end-1)); endfunctiondrc-3.2.2/source/doc/octave/createalldrcplots.m0000644000076400001450000000362013163132315020463 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: createalldrcplots(ls,lc,rs,rc,outdir); ## ## createalldrcplots - Creates all the DRC manual plots ## ## ls = left channel uncorrected source file name ## lc = left channel corrected source file name ## rs = left channel uncorrected source file name ## rc = left channel corrected source file name ## outdir = output directory for eps files function createalldrcplots(ls,lc,rs,rc,outdir); # Creates the basic plots createbasicplots("sesample/ptr.pcm",outdir,"DBP"); # Load the impulse response files lsir = loadpcm(ls); lcir = loadpcm(lc); rsir = loadpcm(rs); rcir = loadpcm(rc); # Creates the Dirac delta dcir = zeros(length(lcir),1); dcir(round(length(dcir) / 2)) = 1.0; # Create the plots for the left channel createdrcplots(lsir,-1,'L Uncorrected',lcir,-1,'L Corrected',outdir,'SR-L'); # Create the plots for the rigth channel createdrcplots(rsir,-1,'R Uncorrected',rcir,-1,'R Corrected',outdir,'SR-R'); # Create the baseline plots createdrcplots(dcir,-1,'Dirac delta',lcir,-1,'L Corrected',outdir,'SR-B'); # Unload the variables used clear lsir lcir rsir rcir dcir; endfunction drc-3.2.2/source/doc/octave/mklrxo.m0000644000076400001450000000415611320622700016270 0ustar denisitadm## Copyright (C) 2008 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: [lp, hp] = mklrxo(fs,lpd,lpf,lpo,lpn,lpw,hpd,hpf,hpo,hpn,hpw) ## ## Makes an LR24 FIR xover pair ## ## fs: sample rate ## lpd: lowpass delay ## lpf: lowpass xover frequency ## lpo: lowpass xover half order ## lpn: lowpass xover filter length ## lpw: lowpass xover window start, from the end, 0 = no window ## hpd: highpass delay ## hpf: highpass xover frequency ## hpo: highpass xover half order ## hpn: highpass xover filter length ## hpw: highpass xover window start, from the end, 0 = no window ## ## Example: ## ## [lp, hp] = mklrxo(44100,0,80,2,4096,512,0,80,2,4096,512); ## function [lp, hp] = mklrxo(fs,lpd,lpf,lpo,lpn,lpw,hpd,hpf,hpo,hpn,hpw) # Computes the low pass filter [lpb, lpa] = butter(lpo,2 * lpf / fs); # Computes the high pass filter [hpb, hpa] = butter(hpo,2 * hpf / fs,'high'); # Computes the low pass impulse response lp = filter(lpb,lpa,filter(lpb,lpa,[1 zeros(1,lpn - 1)])); lp = prepad(lp(1:(lpn-lpd)),lpn); if (lpw > 0) lp((1 + lpn - lpw):lpn) = lp((1 + lpn - lpw):lpn) .* blackman(2 * lpw)((lpw+1):(2 * lpw))'; endif # Computes the high pass impulse response hp = filter(hpb,hpa,filter(hpb,hpa,[1 zeros(1,hpn - 1)])); hp = prepad(hp(1:(hpn-hpd)),hpn); if (hpw > 0) hp((1 + hpn - hpw):hpn) = hp((1 + hpn - hpw):hpn) .* blackman(2 * hpw)((hpw+1):(2 * hpw))'; endif endfunctiondrc-3.2.2/source/doc/octave/ub3splinex.m0000644000076400001450000000366411320622700017053 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: Y = ub3splinex(XN,YN,X) ## ## Compute the value of the uniform cubic B spline ## defined by XN and YN in the point X function Y = ub3splinex(XN,YN,X) # Find the spline interval by # dichotomic search N = length(XN); IL = 1; IR = N; while (IR - IL > 1) IP = floor((IR + IL) / 2); if (XN(IP) > X) IR = IP; else IL = IP; endif endwhile # Remap X following the spline interval RX = (X - XN(IL)) / (XN(IR) - XN(IL)); # Set the starting output value Y = 0.0; # Set the blending factor for IL - 1 # (((-t+3)*t-3)*t+1)/6 BV = (((-RX + 3.0) * RX - 3.0) * RX + 1.0) / 6.0; if (IL > 1) Y += YN(IL - 1) * BV; else Y += (2.0 * YN(1) - YN(2)) * BV; endif # Set the blending factor for IL # (((3*t-6)*t)*t+4)/6 */ BV = (((3.0 * RX - 6.0) * RX) * RX + 4.0) / 6.0; Y += YN(IL) * BV; # Set the blending factor for IR # (((-3*t+3)*t+3)*t+1)/6 BV = (((-3.0 * RX + 3.0) * RX + 3.0) * RX + 1.0) / 6.0; Y += YN(IR) * BV; # Set the blending factor for IR + 1 # (t*t*t)/6 BV = (RX * RX * RX) / 6.0; if (IR + 1 <= N) Y += YN(IR + 1) * BV; else Y += (2.0 * YN(N) - YN(N - 1)) * BV; endif endfunctiondrc-3.2.2/source/doc/octave/iupsample.m0000644000076400001450000000251511320622700016750 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: us = iupsample(is, uf, flen, fcut, att) ## ## Upsample is by uf times (integer) with a filter ## flen taps long, fcut normalized cutoff frequency ## and att dB of stopband attenuation. If att is negative ## a Blackman window is used. function us = iupsample(is, uf, flen, fcut, att) uf = floor(uf); ul = length(is) * uf; us = zeros(ul,1); us(1:uf:ul) = is; if (att < 0) us = fftconv(us, lowpassfir(flen,fcut/uf)' .* blackman(flen)); else us = fftconv(us, lowpassfir(flen,fcut/uf)' .* chebwin(flen,att)); endif endfunctiondrc-3.2.2/source/doc/octave/highpassfir.m0000644000076400001450000000216211320622700017256 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: f = highpassfir(n,fc) ## ## Compute and unwindowed highpass FIR filter ## ## n = filter len, if n is even an n-1 filter is generated ## fc = normalized cutoff frequency function f = highpassfir(n,fc) ho = fix(n/2); c = pi * fc; f = -sin(c * (1:ho)) ./ (pi * (1:ho)); f = [ f(ho:-1:1) (1-fc) f ]; endfunctiondrc-3.2.2/source/doc/octave/rt60.m0000644000076400001450000001041511320622700015542 0ustar denisitadm## Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## ## usage: [rt, r2] = rt60(fs,ir,ic,rtf,rts,rta,fl,at) ## ## Compute the rt60 for the given frequency ranges. ## Returns an array with length(rtf) - 1 values. ## r2 contains the correlation coefficients of the linear ## regressions to the Schroeder backward integration. ## ## fs: sample rate. ## ir: impulse response. ## ic: impulse center, -1 for automatic identification. ## rtf: array with the rt60 frequency bands. ## rts: initial sample after the impulse center where the rt60 computation starts ## if rts < 0, then the computatin starts at the first sample with ## attenuation rts. ## rta: attenuation, in dB, after the inital sample where the rt60 computation stops. ## fl: length of the filter used for the band filtering, ## if fl < 0 a butterwoth filter of order abs(fl) is used. ## at: stopband attenuation for the band filters, if fl < 0 ## and at > 0 then a double filtering with intermediate time reversal ## is used to achieve a linear phase filter response. ## ## Examples: ## ## Standard ISO 1/3 octave RT60 analysis ## ## [cf, fb] = oct3bands(); ## rt = rt60(44100,ir,-1,fb,-5,-30,-3,0) ## ## Equivalent FIR linear phase analysis ## ## [cf, fb] = oct3bands(); ## rt = rt60(44100,ir,-1,fb,-5,-30,16384,90) ## ## Equivalent IIR double filtering linear phase analysis ## ## [cf, fb] = oct3bands(); ## rt = rt60(44100,ir,-1,fb,-5,-30,-2,1) ## ## Note: usually the linear phase analysis, either FIR or IIR, provides ## more stable and reliable results, especially at the lowest frequencies ## function [rt, r2] = rt60(fs,ir,ic,rtf,rts,rta,fl,at); # Find the impulse center if needed if (ic < 0) [m,ic] = max(abs(hilbert(ir))); endif # Check the kind of filter to be used if (fl > 0) # Computes the filter window fw = chebwin(fl,at)'; # Computes the filtered impulse center fic = round(ic + (fl - 1) / 2); else fic = ic; endif # Allocates the output arrays rt = zeros(1,length(rtf) - 1); r2 = zeros(1,length(rtf) - 1); # Cycles on the frequency ranges for cb = 1:(length(rtf) - 1) # Check the kind of filter to be used if (fl > 0) # Computes the current filter bf = bandpassfir(fl,2 * rtf(cb) / fs,2 * rtf(cb + 1) / fs) .* fw; # Computes the band ir bir = fftconv(bf,ir); else # Computes the current filter [bfb, bfa] = butter(-fl,[min(1,2 * rtf(cb) / fs),min(1,2 * rtf(cb + 1) / fs)]); # Computes the band ir bir = filter(bfb,bfa,ir); if (at > 0) bir(length(bir):-1:1) = filter(bfb,bfa,bir((length(bir):-1:1))); endif endif # Computes the Schroeder backward integration iidc(length(bir):-1:1) = cumsum(bir(length(bir):-1:1).^2); # Normalize the backward integration iidc = iidc / iidc(1); # Convert to log scale iidc = 10 * log10(iidc); # Check if the first sample need to be found if (rts < 0) # Find the index of the start attenuation iai = min(find(iidc <= rts)); # Assign the attenuation at the start point sat = iidc(iai); else # Find the attenuation at the start point sat = iidc(fic + rts); # Assign the start point iai = fic + rts; endif # Find the index of the stop attenuation sai = min(find(iidc <= (sat + rta))); # Check if the stop attenuation has been found if (sai > 0) # Computes the linear slope [irs, S] = polyfit((0:(sai - iai)) / fs,iidc(iai:sai),1); # Assign the rt60 and the correlation coefficient rt(cb) = -60 / irs(1); r2(cb) = corrcoef(iidc(iai:sai),S.yf); endif endfor endfunctiondrc-3.2.2/source/doc/octave/savepcm.m0000644000076400001450000000203311320622700016402 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: savepcm(pcm,fname) ## ## savepcm: saves a pcm raw file in DRC format ## ## pcm = pcm raw signal ## fname = pcm file name function savepcm(pcm,fname); f = fopen(fname,"wb"); fwrite(f,pcm,"float32"); fclose(f); endfunction drc-3.2.2/source/doc/octave/barkbwidth.m0000644000076400001450000000214211320622700017066 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: bw = barkbwidth(fp) ## ## Compute the Bark scale bandwidth for an array of ## frequency points ## ## fp = frequency points array function bw = barkbwidth(fp) if (nargin != 1) usage("bw = barkbwidth(fp)"); endif # Computes the bandwidths bw = 94 + 71 * ((fp / 1000) .^ (3/2)); endfunctiondrc-3.2.2/source/doc/octave/fbslprefilt.m0000644000076400001450000000303311320622700017261 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: f = fbslprefilt(sf, sw, ef, ew, we, np) ## ## Compute the bilinear transformation based ## prefiltering cutoff frequencies ## ## sf = start frequency ## sw = start window ## ef = end frequency ## ew = end window ## we = window exponent ## np = number of points function f = fbslprefilt(sf, sw, ef, ew, we, np) if (nargin != 6) usage("f = fbslprefilt(sf, sw, ef, ew, we, np)"); endif # Computes the prefiltering coefficients we = -1 + (we ^ 4) * (sf / ef); # Remap the window size between 0 and 1 in reverse order w = linspace(sw - ew,0,np) / (sw - ew); # Computes the filter cut frequency using a bilinear transform # f = (w * (1 + we)) / (1 + w * we) f = sf + ((ef - sf) * (w * (1 + we)) ./ (1 + w * we)); endfunctiondrc-3.2.2/source/doc/octave/wbslprefilt.m0000644000076400001450000000300111320622700017275 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: w = wbslprefilt(sf, sw, ef, ew, we, np) ## ## Compute the bilinear transformation based ## prefiltering window lengths ## ## sf = start frequency ## sw = start window ## ef = end frequency ## ew = end window ## we = window exponent ## np = number of points function w = wbslprefilt(sf, sw, ef, ew, we, np) if (nargin != 6) usage("w = wbslprefilt(sf, sw, ef, ew, we, np)"); endif # Computes the prefiltering coefficients we = -1 + (we ^ 4) * (sf / ef); # Remap the cuf frequency between 0 and 1 f = linspace(0,ef - sf,np) / (ef - sf); # Computes the window lengths using an inverse bilinear transform # w = f / (l + 1 - f * l) w = ew + (sw - ew) * (1 - (f ./ ((we + 1) - f * we))); endfunctiondrc-3.2.2/source/doc/octave/sesample/0000755000076400001450000000000013165107357016420 5ustar denisitadmdrc-3.2.2/source/doc/octave/sesample/ptr.pcm0000644000076400001450000277777411024777474017772 0ustar denisitadm10ư31$1@50R:00H1P0QA/A]0:`.uu06%a1}0p\q0ߣ!/Eے ^0-/C \;̘0/U"eZ10S`M0݋߯}0~&(yΰS3L29n-ˑ5:S00_0߮Z/ w/Q002v 4߮݋l/Y0@ׅ0'Pp?\/7qq/x'Kp/8 0xq08uJ#YV$0D ,6<)u/ /D/o/*/p0ӯ,,C_1;\s.lX0A1 */ذm0.cq.9n-V0E.V>錰Q/qR:0֧/cׯ %/$\0_10r0Cw<06>/ٙ/!fLΰ3p. נX_?$\0|&0b0.i0ˑ/?0x/ lߣ/H/5ů=60?M0gEj0//1Pr0a/^0A {`q/G8<)/q0n-ï?/zG0n/݋/D`M .!bQA/ai/D-\sߣ#/fSEԮ/mNٙ~&x/:`/Eےl߭߬\/0EԮ/=:g.C/*'/AL0l/ZL0H\m/ҵ/v3/+(v݋n.//ڮR:8u/l+>(:gIU04nj )֧:g.D/E80) 0)0D.mN0^0xX֧.X00Ԯ0WVj;:gɯު="4R:0}0/h°_10e`/ު01/گmN/{/߰5E/4d0F121<)T/ڮYa0!jwa/v 0p/`M~Ұ' "0 Y0+0c0++08/r30(vnj/_/ޝ0O//v/Af~&? 0//D.+/'/10xs2_/G毷xŰ~&0ު0nj$/*ŴM˯?]0xs0נ0l3:`el3a.n.Eے/߭cW/r010ٙ/Y.,0|Y //A0߭6>/Lު0C//Qu/ڮk /+/Z/ѯZ0R:0S3.K/֓00 +݋ԯ5/j;/xs0Sd0/:`el3Q90E.0-:gIv/.-r08.A/Tk /=".k ./Pݽ1/8u/l3/q/:gI0T,h/'/دS3/>/ `Mm/~&0 / /*/~&/0!b6>0ߣ/'}06>/h/x//lD?!. F݋xDٙwnî௰.0mN._/,06;r/n//N06>+v 0/^:1{( {0M0мt ƯZzIc0Ͱ1Jկk 0"'0hB50l3$\?.}10ު/-݋./=/ܮ:gɰR:0/$\:`e.r3*ﯻ\s0(DEےmN/xcW/,/zeP0H/tk8:`.`M$\U\.SmN/ %0q0É'}C0//10ބ~&/Q0N0^/ %/ܮr30?!.09n-6//v._C /|ٯ̃_$ 0 FxSDVWop./7C&fG80r/!mNˊ=/9nC0%U+="~&0'5Ẽ=;0-/D02,Nyg0 Dinj-/I04?!ְFJ/e I0D_//\/5j;/_/n%U/D\mZ}ߣ/l,S3L/:040\/S0<){/ܯުD6>V010uV6֧.Eے0nj0uC(v-/D՚0"/\J#ߣ#0nj.50_Ic05E௰G8/g/<)nj(0\/k >s0$-.Dïr/-`M/O//0Q/\s ="0ohBk .MK00V0 ˑ0QA.F/k T,/ߣ#/b0/k 0K0n0ԭfLN`M֧/:gɮy55FJ09n-/`ͯR:0/ٙ/D-G<)_/l*X0`/QƢ0݋/D/ 06>.j;/=6 F/{^(-(ˑeZ0.9n-:gI/G/\/_=..m0\󮋌/ï8u-l3݋= h0ߣ#09n-(-k 00 -H0v/ˊ!S0Dm/l/+jL&NG8/55/O/^ze/ބl,_-T,0D/.g0?/10=/j/a^/:gIM0./1S00D/{^/l,ު0q10k '0nj un\\0O09n-0?0  /'0ڰ*o0!/t l$\g.a=_.2/+2/l;˟D.נ/\s/_0:/h$)/ e0/:`e/ F0vl30/yl40Eے/v H1wn0X0\.:gI/:gI.:gI0nj =/D.ѯl3-0l*/9n-,/֧w/l/l3-+x/@/:gI.'Gc0x08u"njk ai.x.O@//ڭaޯzeP0+ai//Z..:gI.Xv0?!j;/-wT. (0"~0C/ 0/fS20֌L0-ȯgCZ0)0~0ߣ/nj|Y//^-H/%U+|g0`/yl40hBT,h/C8u0%0D_.[0&N/ބ:5]0`/*o<;0!/k .м/{"0V>0 %/:gIٙO@:g.мqS3̯/]u*0.fS/C.mN.^0h¯fLN/5:gIi|Y(v-A///-ȯ6>.>0:gI-_0/^v /(.'.0ǔ0{../e_// ,/eZT(v-,ٙk xtk/_/^C/GJ9n-/h00<0֯̃/r0ު0 / (0"0:g/ /_{/Q_-B~ 08u.T,h0E/U.ˊ0lC\C/"/E.z.x.Én/$\x/6>̼ 0&K0ߣ#0'Gc/0 .qU]Q0Ѯ X/H\B~ '.~&9n-/k j/"PY09n./_.fLN֧C:0:`e0D0د>0(-:gI/n5E/ުo&/-ҵ/0֧l/tk0FJ0FJ:`审p.6>.a8<Ļ!/?0T,/j0L//9nM˯T,诡]尅/Y/\C/ҵ/!⯅/( /"t/XO0o 0:`./(+0+/ot0=&0 .9n- .]<[:gIm//T?:/T,诖ůxm/P0]<[0S0Z诞.!b_0.l0*0):`e./'.$\/pHX-0,/4.O0ﯛ/// e.c*oE./5/\s(@.᮳/e0./+0.ˊ/0%U/ '5E0r3/''/5ů*0tc:`e=0E.<0-H0k 02AF//Zm/]+/FJ/{l30_1/p\A0l35E0nj 8/Q0ł/WFJկC/%Ur/U0m-/nj/U"ρ+/V0鬲00ߣ#/(_.80/e0[005E0/XySdߣ/D/:gɯ.0ۯx/EԮ!/~&0.tk0n-O/)/X5/G80A//.H//nX./_aޮ:J../ߣ#0ܯ(/i@0ưî"Q9n-/l3yl/9nˑ/cW/C``~֧/C 0:gɭau/"@J*կˑ 9n-X /:NC  / /oc%:g.@J;P8u-G80k 0W/x*/C02/nj.D:`.mN/:g/6>hB0cׯEԮ"0C .ԮA5/l3+/{/ҵ.d(+UaifLίD.6 1QA/q0"/%0c.خM0/Ny/G0l3ZH0cW.`/+xs0hB/򼥯rQ06-_0/G0(v:g/jFʯ\s=.-H/7:`-/6>.a/:j.7\A//lYު//.cK0/ocQŰcׯ8/0ˑ/8u/{/Xs0T0֧-x呱t/w1!0:gI(.0 P0v/R:0/njC&Nǯ0L/0$\="0a/l"/ e5EԮ6>݋/T.ު'}/U^ӰGfT.6o&AmN.nD6-+L/0Dު/(v/H1!vx.!b/,]0|ɦ0k P0v0ҵ/@J0x/'/݋l3/:g.gE/ F(D9n.E.l+(v-\P0:`e._/_/UQA/(.'.(@0(v.8ˊ!0\/%0S3̮k 0//Z/QAߣ#k .' 0['GcQA/\/l3,5E"~="0 F/C 7-H?l<'}00oc/k -0afSx/8u. F"/p\A0נ/L/ ֧-6mNE/ѯx.01/f0r/ٙ/Yq.+/./D0l3ylDpX06C߬ުqv ,l3H*(@.c0{^/ai/;0=0ު/(0T,l-l+~&0k .l38u/ /'/S/AL50t/c/G/_0-H0(vt D9nK/" zePîݯnj 2,ҵwޯl3,p0I*c/.mNlZj;3/k Ư5'^8u/)0/t0;˟/Zz݋G80kx0^/'/="ު0D.ٙ/+C0̃=0 (ٙм/0ބ/^/'ۯV$.N!k .nj.*ov[ ,0(-[QnT,hł .1Prԯ֧-_S3L.n0v  0 D/oc%0'(E5*ł?/ / 0/ZaޯR:'}ze/FʯD/ /ބy50U^S0/uC0_ 0<):gɮlx0(#8l3w t"/V$0) ?!`ͯ../mN0a(0h)nj/Q*o/G80/nꭞ.8u?0x/-./ ,,/߮?/F/^0:`e .0g0Q/l /88ulX/nj/ _נhB.c. /?!.QA.:`e0X/|ٯ+:gɯQ9/c/v0+0'./3H/'}. U/18u/0:gI /򼥯1/yl/JկAEے /ٙ/3T0K/#80)/:0l30t.>(E./x>TZz$\6.|Y/t/ 0мGۯh/gE/(04Q/hf(WZ/>ԯ/.="/ԯU"/D4Q:`.D:`e0a//e0?!l3.-:=aU5E/R1U^Ӱ0G'0ai/+8u/__10nh¯/.;"~/./D.;0Cw<0k _ߣ#/@n/`0ON.FJ/G8n1:C//+DˊE0q"S3̮P/./S3L8u-0 /l3.ˑ00%M/09n$ Q9Af0Dnj./:gIT,h/87l\T,'.`M-/nj- %R+/-./:gI-P0T,hC!.yl/ު/֧. 0k_180T/".'Gc-H'p/݋.t:gI-CIc +r3O!ˊ!/o*VETSطS/ n0Ny/+0o0x0.c/e0wziۯު/_0d 0 0 %/ /נ/lq//S3.i@0Z/D /?qNX^/(.8uǭ//(hB/l3/&NGߣfS2-/nj05E0 %/0 0//(//e/ Ʈ+0?/87S/QA/2]="//="/_-"~0<)G80!|'0'/ܯE810ło {`yl4!bZhU/v 8.|L/0802M/.0/ˑ/ AY0k/.c\.t/~*﯇Q/D-0/qylq:gI/AxsZ0 D0/ѯT+mNX0>(0o0ڻ0?!.06>"./{^l/a.a֧../`M0050pů<ĻS3L:qh)0[/ :`e/cW/`ͯ.cq/I*= n0@ʯS3L/8u.1.8/X)/[0|.a/6>0&N/'nꮞZzmN/6>e00ٙ3"6j۫:gɯ=zE08.:`e/ 5E/"/ai//G/!.%U+0 I0l3.cׯNyO! 0//+mNa0i@D< yl4h/QAgzeЯ/-{ 0}/C0\/I*/:0ު.(@ܯ10$ / P0r3/|/'/'/Z.-/~R(/l3G/.k ./JU0ZL|'cW|&0D0/Z.Q9FJ?4H0.{^l/6.Y0k /L//Z.|/gEj 5E/ҵ*o0.qDX﩯?!-H6KPY05//U/|ɦT,该X0nj!Dy/NygsJ$p^5sϯ\C/l0T0Zz/#80=W50ˑU"aE >1Gf\0X͵(ˑ0m0e!G)/H*. /݋m0h¯/ߣ\Ca^&NG0{/@S0.c/0ł_5uFJ_":0~&0ůկt1֓00D.:`../S3̯9n.VR:0.0 0/3H/A/Z̯5/Nyxs^V>𢯒?/4EԮ^05.$ 0 (S /8uV?/@ʯR:0*o/D-q(v/l,0m//Z.8u/J/c/Jn0 i0r3`ͯԯD,,:gɬ݋^0ߣ x/֧P0nj<0~/9n--,.#1O06.=;0]<ۯCů\ߣ݋/ҵ.j;9n-nj.-H0AFr3EԮ//V/>D,D-QAyl.د 8u/&NǮ @?M08i~ү9n-g:`8u//l=.֧1S/S3.:ު/ҵ/C 0+/S3L/QAl-1S/^6>.ai d(+0u/gEꯘ+Ԯ6 ֧{^l0S3L0qد/Z.8u.ar/-~&18u[/R:/x/+/QA/80x.̘_ү!b/xs݋l3,(@v Fʯ ̼E.j\ѫq/N6"~q/nx0}/l3/\C/~&|t 0l3/_V>0 e0p#/!"0XE0;0 0\J08u..'./^:-,//Z0Ya0%U+QuD0-Ģ0-H0hB/:gI//mί/ٙ/l ˊ! 0Dwҵ1q.Kw0:/9n8700)0"~a/0 0lZL/5/_ـeZ/xs87//8i./(vުa1/e5.TB~ \J#:`.C :`e:gɯ/>(/ڮ) 0:gɮ%U/21!b06>/j;0м5mN.D.Cf/4аt -.8uC0\s0T./Z/8^50ߣ0֌L0\ . ,Y0qH0߭:g._/U/1. %/1S/0:g-:gɮE.O/yl.>ԯfLή/Lv+ e݋:g/gEjnj.0g0nꭦ0+-j;1ӯ/%U8u.{{^/. .x/>(_﯇mH/) //fL/M˯6.q.D`0FJ/Vqnj {` F/,,/SqU]0ߣ#/֧/A毡p/?!.0ˊ %0_1/5EtFJeZ/SG毷xX/Z+0lk .<Ļ/8u.@J0(-l?Q/ .Bկ0(@6S/(v-EԮł/ު.:`.nj/"~/l<4/xs///R:/*/f/ބ/ %0-B~/ު/]/0݋/ =".֧.0-H/.c/qk ./](n. k :`e/mL0 %ү )/a^/V$0/+/'`L .0tk0cׯYF/3ȯ=ׯ/گ߯cW.="fS20a/ł/u/ /C.T.zn.x-o&///ڮC#8 /x00%06 0^5w"~Y0870/1/9n-/,p.a^oc/6>l3a^ %9n.l3F/:0ԭo&0x/:gI ۯ|r0:`fLNL:ު*S.8u-x(D&NGj"0 ބ0&/{^/@0H/./90/0q0S3/:`ẽ0AqAx/:`e/%U+058uVm/mN/v.>(,,-/o0.a/ ./Fm0/fSZ/-/Eoc%0 /6>EԮ/ MK/נ/'/.S0uCH\Eے.f0 /Яm^(v/ˑ/_EC0<Ļ:bmή/ڮ/`0xs.Ax/6>/wr0.4Diҵr'0/!b/g08u-U/ ɯw^0 F.S3̯,.Qү="-fcW//>s?!./R:/xlcW/v/ٙǯ)0o&0/ڮ87/t/H\/D/8S3L/6./ 0K/_/54d mNDSD-t'}^ZLT,hmNl3 {ߣZhk .?/qX0q0X0C֧.,,0S3L/".\CÉ/SC k // /) /k //k /(-T,h/{T.U"0/j .ů7ު/0E/:`e.;0U/g/֌/T]?D0#81/Y&0/lf0.S3.ۮwA-05ߣ#+/0 ''} /{^ D{;0<)/q" r l3+ ek گhBEےR:0Zz/x.|.d[𢯅.[ 0(@/\vH0Ic  /o/c>00_+/ F@ʮP=/5y0ɯgEj0/Z0/м/O/C/i⏰(v9n.X0l,./rd(/V/k -x.L//Kuu/-H/Y00/./=/nj ݋C D|ɦ/?/.a,0X0ˑacׯ>(xs0_/'Gcx.8u/'.6>gEj/:gI/(]tk/8.}~/0W0,/ܮq'"R:0):gI/,,݋mN.=/(v-6p\/&Nǯ(v&K0q/(v-x0 /v (v.6>.+DDG/T,h0c/"%(v/.;B~ ^\8u/\scWfS2 {`fS/5/ܯ (/o/A./.$\Nyl/?/.330.c6>.l3+~080Wگ0k /-ȯ .1?/E*//nj0"'0b0/$/}0/}^0/.5ů87k l毟88uK/A/p\A0/.\/ 0_0Vj\0eZ0q8u.D0r30.l0~&nj8umήqh¯1S0\s/3HZ0T1S:`尃uñxs0 F01S'D- 0U߯0_X0G毿<0j/C0(v.QA/X0߭ 0+0/q0nj/ۯ+0-H/8u/֧/.a$0/گ(vl3j0֧/0:gI֧0H*070k +//ѯ+/ߣ#0ٙ*Ԯ P %R0"/0yl/ߣ֧Buu0R:0rѰ{C.(v.֧./ު0Ԯ8 l3.ު/D-ll3-8ul3\0ԯ0\{0lS3/l3(8u0 E5zeP0="0R:0005Ek 0D="  l_.? 0 /FJ0-ȯ:g-CC/ FnzeP/S3̯8u.mNQA0 0=.y3e08u{0l3="D/֧/mNl<)' mNV0j;h/6Q6+Zz/'l".D-+9n-T݋/.(=.70870_R:00`0mή="//'G ߣ0l38u0߮.l3TD(.m/O %0q/a^/:g-ٙ/E.0{K:0݋\lު0p//YO?!.xA:`e/q0=="0݋/8/6/֧9n-/D.t|/06> /8.c.l-?!0-.:gI/50@J0q/(. 0nj/l3-iIqnj/-D'C0:g/k 0nj.:_.ު0l݋l="0/9n-hBl3:g/^//ߣ#0D/:`/yD.*o0DpXh0DD/C/T,/:gIl40-H/^40ait0-5/+\.0R:00k / 0:`QAZ̯K/R:0/ïq0p10ߣ#:b0E8*o/:gIR:l3/ 0{//ew0. F00qٙ:`寫 /뷯0H10'/m/l*/D'/:gɭ %8uk -H0ze/9n-/ުxa.﩯=Fʯ:gI8QA:g.8u/ /E/ٙ/̃=0"/9n-\/jmNބ05݋/ F06'0QD/ڮ.nj/~RVk E.5/]D.U %. /S3̯/É*.q/5>(/0x.:gI=/үj"נv 0D. /߯_0J\(0/)/S3̯:`e0(vx(/k /r0GcW/ˑv/_//xmί̘/806/'ٙ/'8. C6>DQƤ/p/njS300,,/T,D֧0`ͯ``/t(vsO0yՖX0\!b/l39n-/$/l-/T0(݋:gI`QA/.0+0:g/8uD\s:gIl30x/_.QԮl.wk /5E֧/:gI/-.80S3̯R:0/?S3/cW njl3/| /_l3/5/8uR:0:gI0݋y~z0 (l-]<ۯį:`e/l/k /a_mN/8.P/j;n?/8sxk  .q/Z0(į-(v/nj8/wѯ_l3-8l3-l.{0nj0c///l3#/QAT6.:gI0'00G/_(.78uQA08:gI/R:0 %04ߣ#:`e:gI.:0oc89n/8u m/݋X/:`e/k /9nxT/j8uR:݋(v/݋_5/p/D._:gɮު0D0:`:g/l3/G8mίٙ!8ul3-l\s/leZ/A/*0(mN/:gIl/l3/'.ְ/?].DC/nj/Z/ުv6>0l3D0:g-߭/.@J0-H 0//ܯT/^0+0?0ł0S3//5ٙ/L0 +/%U/m /=W0m0zeP0ZL~&}/ï 0ٙ/:gɮ/(v/'0^0ҵ-0D.0=":gɭ6/w0'Gc0/8/l3-o&0Zh0(.(v/0l387 0 %_:gI/q.C/l,k .8.6>x(l._.:gI.Lg0k /!0 in6J//g0p"~!/Y00l3-A0n/CTD/xsn߯9n-/.R:0{/.tD6>S3̰,S3̯8u.Ѯk .0o8u=/Z//(.ٙ/ۯ //گ/nj/VYDQ///j//Eے/!b'DcW0*T,/6>./'!⯺cׯ/ /(v:`e0./[Q Я/Z/l3_.<^0nj(.6.î10= ="(.a^0C:gI9n-ίD="0 ݋I*=/k (k %S3̯(-< 0ۯl,.0ߣ#0 0/.+mί֧.eq/ ݋._/:gɭ/5{ 0_.۰5EH12,) D/ބ01/0(v0./q0zeЯFʱ|W1i:g/R:0{Yh0נx0mN 0="/Z/{- b0X"~0(vD0/ 0(v.:g-'G_.Aѯ9n:`/D /.c/DC/K\ai87R:.a0/Zx/p06/C0*0(// 0<)nC 08u0l-6>/S3LR:/T/6>UC9n-0cׯS3LD=Nygl3/9n//O@0pyl4&K.{9n-/T<_`ͯ}/(v./ 0'/EԮxs/9n.0_@0ު/xs0^0CQA֧._11S8u/k .0z0l,:g/ 0((v /?9nx/nj/6>.nj.B0mNުC>(vC/hBR:/Q9050+0-H0(v/C^^5خį!ͱ/o&0נ/ï=:g/O/a^/D.n %U/t(/.'/.pTD/?l-C :(_/֧/=/ҵ/FZh/d0x.a/l -zeP//ڮ /l3-Hܯr0]0/08u.nj0Dl,xˑ0jl3D8u:`e/ZL0ˑ0l3^Dl3-x F/:`e/xs/)rjk  QA:gIqj;0m/ߣS}03H0j/lE.мFߣ#j;8uj/5/tk08u-)D0ήD0S3L.9n %k ,(0 3H/%U+/`M0"'rGZL.:gI/K0_0.xsOѯ (0p.fS209nl,n/֧. (0j;..㮱łQ//T /Z3H\s/8u0k /ѯ|ٯl3+0ބ*o550 /ڮ6Q90ٙٙ/&N/ïx(v.*נ.~Q/%Q9ˑk  l38u/ïq{/Eے. {`0n/' k =. %:g.h/nꮚ//ZJ#Y0 0zePD0//l3y<)0/8//kmrѯ/9nFJł0_/'08u6A/l^0:`e( //QA0D.Ny(.k .k .(/گ`MH1+ 0(@/xs0:gI.l0k _.8//ٙ!b0o&0nj/.C06>/'l3-^.l0/ra^70r3+nj./0_38ï.a/a^'/QA(v/(./S3L/ DZz2/0D-(cׯ./S3L./ /D/6/q0,0C0_O0ބ/-1ު0$90֧/gD:`ecWlf"/֧/2/D-ٙ/Jկ݋.C/lÉ/l.8u/vܯ(./Z Ư \C/1S50870ma0{v ,lF/$/x0!/q0.r0q,.S+k j\cׯCh$0*o/ڭV {yl4Eے/_./Z8u/_0ܯk .7DD.ѯ/Z.D-\s0m/X0/.!b/L1(@//Z/=/!.lci{6//,. lp0l/0Cq/%`ͯl+l,݋C /TE.A?njD.!⯍~/="h.vj;Z/ :gɮٙ/q/8u/D݋/-H/)050D0C\. 0t.l-eZcު0U0)/L0mN/o/DS3/p.8uۯ/Z C/x_3x0/c/mήxs %/.X"<) %6/ǭ/Él3/+0/i/tk0:g/u/"~Zz?/ߣ/="$ 7p8ua^cW8u/?0 /Qp?0/+08utxyl0_/cׯ :gɮ/C U0:gIz00QA087hB/l3/l3.l30ͯC~R{06>dۯ9nx.v/:gɮA/l_-Y00E. gE2,k 0:g.6>8u/z/XDmN-0/i .l* 0G{߮D//U(v.֧9n-00/QA/T:g.Վ0L0X0͵k /?0$ ="/j;/?!.ZL8<¯R:Jկ8u/G8߭A/:0JU70ߣ50nj.A0D.="0"'t A04`/(vnꮞ-暰/D:g.xs/Q /6.?/8u/6>/n/j/eZ:`e/n(-D {`:`eD./k fL/U"0/.808u/aޯ֧.c/ïk /мq//|'1l3EԮv 0*=".9n-\sl.l3,ބ/4/QA/]"x0nj/ /870(v9n-/S3̯xs/?!.cׯ FR:0/l3.(.x/1!⯓1//x %m/=x0_/QA/x)0龯E.:gIp/(v/8/Q/D/T,hj/S0/:`.T..ᯓ1S/L/8uF/T/=";01SmN/9n8u/=T/ѯ&NG0Dp0_\k $*$=QA.'0ˊ!0l/O/gE/8i[/Z̯G8.8շ Fj;:g/wA-o0l3:gI.{^Gw/򼥰>(:gɰY&Nyg87/>( IE݋L0l3c׮W/v/`M/l/|MM0C0$\0ߣ#0?!.0cWO0Q90l8/m/QAA0V>05/_30Cw<0:g/q/ //uu0=.{/:gɭ:gI-5ů`/u/[p/p߭\s/ /K/:9n-087k _ T/گ?000"?0//~&կ ,Eے/6;0:gI6>.G80j;/R:/'"~(vު0 ֯70x/N0 0J\(0U0/_/r0 k O@0k MK0vB060 {/vH0_./<;870*l3//ZX0 /(- ="/l_=/= c?x0ҵo&l30R:/ u&h¯֧. Ư/qE0/qmή6>.l3,5/El3o&/'-/40{/?0m.QA/.QA/U0/]m//T/T,/mN/%U0.0/q-aiq0,,/6><)0 {'.a/'/֧/fS/"'C 0nj]=_,M0EԮT,./ED 0Eے9n-0/ҵ.l3-k /o&/nj.e!G0ު-oc/k /:gI:`.xS3.<"~ ƯS3̯r/߯/ai/<0x F/k .= l3}njмn=/yl40_/h-6. :gɮ:`EtqhQkmή_z0}/.c/6>:gI.~/n9n-/6/ .87/1l0]k /C/8(v.ުl3j/j;0MK0 _/֧l30aޯWگ'/,,2,.{^ll3//ߣ/u/0!:`e/ ,60QA9n ,60\/D0x':gɮ08706k0g/.k /D="9n.Tnj5/$/F1/ZZz6aޮxs\s0QA߮60Dxs0/\߮1VlмN(.{(v0i0\s!/cW0 ƯDS3L-Ȯ^/k :gɭ(-ު\nꭠ.V/Gf0qn- m8w70cWDl3087/@./D/\s/ 't/eZDE"'_3="6%k . F/a^0[{C 0Eے(-L/ F/D. ƯR:A0Hh˰د>(+0O, ZB/(eZ0m.Q09n.0W/8u70D/k /M0]080m0Fʯ-0/ު0C 2!-S3L06/݋/S3L008uZ0\J/?09n_ـ0="/:gI.ު0/D.'0tX0(- 40)9Q9/ҵ:gID-?!:gI/̃=/sR)^/_/QA.&N/XO/ Fʯ/ł/k ZT'}yl4="/\s/R:0/Xw/Y/X/ˑ/"~/Pٮx֧.T,9nQA// //8u-Ny 0D0 .60/9ns5E/ρ0./$\0R:0/H1!_="8(|Bk .l3/<)\/ҵ/6./.hB/k /.a/8u.f80_(.xs0:gI.n.ze/:0wr/ 6>/C/݋_/ //D0 /.Ny/="/(v:g-R:jQAԮT3mήR:r0m. X/m.w/.*/n.1/"'8u߮lzeЯlG毦Q(0/C 0î/T0>(/sO/3/S3L/ۯS3LԮ6>֧4/0hw0D/=Z/pԮuu_l.ߣN08u-{n/xl3K0k .D-+ˑeZ"~/\J00l/'GcF.P0CD.'p0S/&d0\0֧.֧/{// /nj-/9n-(vX//t/ު0O@0p#r ..k 0 /j-**o1ުQ|&5/נ_-Eے/zeP0 0LXO/*ﯮh'/9n/x/"' .eZ/Q/V)xi/.Eےl39n-/v `/\s``~008賖0_ZL0+0 06l3-1S/ =ٙ/D.l3ބ/a/nj.0q.C./կX/A?.֧Ԯtk0o&0-/<)k 0]ѯfLN:`-'ԯx(D/ %="a^'/Dq_/gEѤ,5E/l3/~R0:gɭ(v0/̃/*D nTe70I0iI020/r/eZ+:0x/0 0mN/l-QAr0fS20:`e {/k /lo0Qsnު.w0r302/.nkxL>B0/8/mN/Ԯ8u0/ /hîO0/\/\o& %. {`ZR:08u߭+@*/X6E$\Dit賖îQ9R:0 DF/ {`0`/vDzeP(/0C 0(v-Crx0R:8:`e:`e/6>0"~aiZ/<).g ̼ 8נ/gE F0,,0(-/1/ 0C/$\/_/g/'02/x0/:gI.$ /:gI08ul/0Dدp/򼥯;̃.<;X/QA.+/0߮l35/oc%0aA.a0.33/x/6:gI9@:`eA/;rvo/}^0xs{/FJ0pX/̃=/y֧k ֧.QA@J0.1ӯ108u/;0(v-ު:gI6 //.-H0/֧./4dcׯo&&NG^nF0.Q݋/D/ />(./ڮ/ ֧.="sOAj/"//cWnj_10-/nn.(vq.;˟^0x/=/ߣ#/lH1Xz?/"//Z-//6>/=.xsAfU"Yh¯.wn(nмk 0QA/nꮟ/mN06;0ҵ/l3,l3/t+:`T,/݋/ylj :`e/8u{.'-Cq_1/W/ `Mk 7,{ v HQ߯1/@/yl֧-t|l3//D'00="/< 0n0a0ުTD.q0/h¯]ҵ//Z<C _l8t/*v/0﩯CS@֯0W/>(0_P0F0R:ޡ˯g0ۯ5El3r̃=ߣ#0{^Af/xs2a˸TQA`ͯQ/ /X.Ud[)k .x/*o0yl/2,0mίگ(0aޯp0:gI/Y&0?0 /a.u -H0?0߮>/(v="_x07 W0aޮÉ/R:0^0..|/"/h/kx0.:yl4/t|/ ,D߮/_.xscW/p/+/T,D."'!bq0"~R:008u.:g/&Nǯ:gIFʯ`ͮ?!/נ/ߣ#0 S0|/D-o/<<)(v.+.:`e00yl0_-9n.îˑa/6./a^00:0!/njZ/<)87/+0r38/+k *EԮ/+0A/ {6 zeЯdۯ9n_mή!⯞/(/ٙ.]KUD0Zhůˑ0gEj0l3."'(v."0U/Q/k .a,0. /nj.9nX//FJ'T,/:`寅ٙ/gEjˑ/?0D/0G80/(v0 0Dl3/_.T/n/ %0Qc?0A="//R:08u/vx/R:0/G/֧.C/&NG{_1q+_eZ0k /0#80/U/E.0ˑ0T/D-D.6. /8/D/5\fS݋/{^&N/l+:`e (0.8u0+/hBD0 0.8uA/%U+0ߣ/ł"n0x5ůм4d/֧.:gI.D_+@݋6>.l3/9n-ˊ!0Dp/Aj.D [Q0'Dk D-nj.q+/ e/fn8u.נ//:`.K_l0/t|(XPY0="-?(v<)\J#ܮn/0Eѯ݋D 0 %4/fS2/ï(-q0j/j{0D']/.۴wP/t=.,/ì08u-֓00sϯ//.k +W0]/$90/]<[ 8,00:gɮ*k /:`e/w/(/P_1lҵ/ބ//9n5/_/t|Eے-C?!lA:g/ߣ/:/G+/0/݋"Hn°m.~&R:0+/c/X/_-vB0 F'q0t0t|/geZ_دi01Sl-6/.D-zeP0Y&0ު[/BEQu֯/QA/(@ Яnj)eZ!bLѯ./m''QA0m.'/֧/*o/ł/'t -H/݋.j;09nx %/L(m.(T/"~/0\//)90ٙ.`M^5w8ueZ/fLί뷯دa鯌6~&0Eے0:gI.x/R:00!0cW/XmίAxsa/xs(v/UfS2w:`nj/0C8uA/5/sO0w/݋?0w6>.ޝ.S0Z0ٙ0m88u-$p0m-H /ބ/!00 F/_0J#0 h/!0̃ˊ!1_/5xs0t/,,0gEj`ͯmNm- Ŵ9n-yl4-/_0[Q'/l:gI?/=.&Nǯ6>=".8xïo&I*=߭KEmήY0-͵/݋.:gɰt0?!/QA/8u0_2,м|040נ0 .9n/ 05/.T,h0T,h/QA/00ll30.uu x/ 0N/.֧="/X0=r//мmN0A\/mίxA.H\nj/) ۰C ?!.0l30l,V0>T0ބ/D5x/&NG0="//9n-/_Ԯ8.tn-*/[Q0:gIl3:g. hl3-Ax0Tq/6ZF/:gIԭl3/6-5/Y008{^:`e0p!b6>/:gI.sJp.`ͯߣ/D///Z0C//8ueZ +/l304d0(v0w/k C.QMK0֧(v. 1cW/֯#80߭/8u0 0|&0nj.R:0/=ůQA+ 0/~&mί./:gI.ˑ1/w/Zl/j;/(>(/9n-/^+/F/9nX6+0:`e.R:/D.L/00T,h/(.Dj/e0.l0Α뷯߮L/(@\x/805ED0xs08ug~0M0q.&NǯV$֧.ˊ/ߣ#ߣ#'} į֧.R:/Vnjk /a^0:gɮDмqҵ//Zlu\sԮ :0a^(@0="/xAư:gɮ="_?!:g.֧.錰X0 ֧/(_/ͯCw<0G/:`e/߶@J0/cWcW/0+oc%6k0lު00.ߣ0x0l呰v0ު08u9n-FJ/Z/}QA,\:`e0O)l.(v/נl30l(vDtuï.c0m//v䀰)#~&0Ev yl/l3x/NmŰ./8u/נ/ %/ulˊ6>1s/=.&NG0*/)0E05/(v߬l-6,,nj06/:gI/:`G/j`M0D.m/(@0a,K0A0ï/ڮa/r3/D.Afc0`0c0R:.n(vk /:gɮ5='T,诟0:gI.l31/î:g/6>;˟ԯj;l3.c*.ư߯T8!/- 0n.k ֧0q:g/nn/.c0$0//k {. QA0nj//(/C .6֯70(?MS3Lm//zeЯcW/mήF1f/N0\="l,xt8u.bo0.R:00-H0 F^5w0ު!b/C/]//Z/r!.0Ԯ߮]/ )0t0l+1S0R:/8u:g.ު 08u.ٙ$\0DT/:g/!A.V$//8//mN_5ů|Y/:`߭k QD."/6^DR:ݯQA/+cW/x9n6>._0ު/n/=+7ߣ#/\s.?m0߯ F/.l0XD?l3-L/0ԯDj;0/.-:0/pfS20..v y8u.Ԯ(v//r/_10\J0JU0 /]/./ {/ %R0DlcWmS3L .8u/D-:gIQ%/S3̯{/(S3.'/nxs08u:g-'5/A0B~ 0 0߮/ .\08u-H1!@Jׇs/0ۯ0"~Cq[0ryl݋.]0֧D.Z/r"~/=l-hB0v 0Nyg:`.xq  0k .A0v /0.="/="lٙ//:`e/ /5:`e.|B0$/t/ ="/?R:[Q0м//0jmήk /D0%U+mN.$/{^/m0:gI./|'/ZFJנlt8u.گh¯wn,,Q"'0_/É/ylOn0P/a.(D0֧l3l3 008/80\м/(0{o&SÉ/Z/1龯T,诟8.~0$\HC`M/mN_10݋/D/ (0QA/g0/6>/0_.6]j\0 0 0ބ0Pt/D%U+/mήw9n-._-05ů֧/S3L//Zh/lmί$F/x:g/$\0j;0 0D8u^ZL08k /_=T,h/\?/V>/X/G8/zm80\/dnjD. / g0:gI_.:.E.nj/k /ٙ{./݋/G.YV0ip/j/w"V 0?/?!.l3.'/ԮLg0h¯6eZ0l+X/`/ܯ$\L/O䡯,/E:gI0T,h|0ߣ#/i6/ު0%%0+0D.//FJ/G:D,`ͯL/Z-/]10ڰ' 2,ު0Z/0 .$[Q2So&/PY$\q/'C0o01/k 0+/[zeЯ>(1/'.H/%/j0]aޯ֧/v 0/.c/CJU.U05x݋.S3L(.]0-Q9/ "/4/.k;үԮx_0_/.XH\/-/A/2,0Cśw0ˊ!0L0@0lS3/y5 %6>|ɦ0 U/9n/݋./<)xnj.﩯$_l3.k /ZL0l3-40{^/Fʯׇ/-/89n(k :gɮl30q0n. 8ua/8/.+/>/ӯ:y5X0(.f0/Z/D../JU./2,0h¯߯͵xs/:n.gY//ٙ8.5EC/߬T,h^5w/D.q/__1xa0鬲.DE8/$09/?!/+֌L0nl3.D9n/D8u((v.j;8u.|YcW/Q0֧-X0a00c!`./ˑDp/ /DMKد:/(vyl/ D0O!0I*=0 F/^0cׯ%Ȱl3/:gI!/(v-;҃mNB0rhBS3̯j-/%UQA/_-,.Cq// %/l3/'PF ߣ# /sO *oBT,:`.+0{I*=qU]T,h/Zh~&/t6>ٰﯴr6/2/zeЯ߭-D0*/eZ/E0{^l010 /_:gI>0.Tr0a/m/{^l/ߣ#00D.*J#/>(/(vv0$ 0h_/n//_104dD0'/1nj?0 ^/f(v<:gɯ/./|Y8/D/{ %//_/@JśO}0_/(,կyl4_gE//!`00l"/t߭ł0"/CI0S0+0Q/`/mNC/{ 87'0]Zz.8u/nj/C 0QA/y0߶9n-A/R:0-/֧.0.D8uai.nj>/D'6/s// x賖 / Fp֧X/v//`Mnj/Z.NygΰD-0 .0/mN/cW?/(į8|&#T/F0mN.:gI/:`e/FJ0]0>(:gIҵ/Q..i0߬M.c/a^/:gɭ.ï^mN/7D//6>/A/5'70\/l+nݯQO@=.r?ԯ:`9n-8u/E.\// J#Y/ˑ0=/2#80Eߣ/D50nj-/8u.ł//Y&Q/QAnꮹj;:c0 (0`.龯e0/Z.:gɯ/Z.N D!.:g.o&0Zz0.mN0^//賖9n/Gx>u&/eȰ{мR:/8/D/nzG0xs/n!bAدT,hנ/9n-/R:q8u:gID0jXv/hB/8u/k 6>1aihB0{^l/x߭'// 6*a0:g-C*o/x/ 08u0q/;0/8u.fS/a/Y08u\.\D/_.1S0xocnj/?CmNt/_f/pQANy//l3.V /6>.k |//Eے/|&0݋/QA/,C^>(ï֧..j;(.'/3[T,S3/נ700"/S0E>0Cw<`X20îGf,9n.D6l3SH4c.l3נl+.%q/ɯ/R::g/ٙ'2Ny/\nj"0 EԮ:gI(. D+ F"'03ȯ|/40:gI//n/ 0._10߯}/g/n꭯a0+/hB/:/ߣ#:g-T,h0"~/:gɭx/TT,h0 nj 0G毅ٙ/Zҵ/Xv0/:gI0sϯ/x.-/xs:gɮ\sد:g./Z:g.l_/?*/ / (020eZ/Gf/cWt2/U/AxQA.40/ҵ.__0?/\/l3q0(v./^:ˆ0_k /*o //S (08q0:gI/՚0/'}l0L/?0 %/h¯_-.Ax0D+.:g.870Ax0{"@/T,a//v 03ȯˑ+a,mN鬲l^/l3c/'}D:4R:.ٙ/_..5]ΑQA. {֧-՚"0C/l?087_10=.~&C /t;040j\,,'20./(vˊ//l-k 0/ /n.<)0:gI.6;/֧T0(%U/J09nk .qO@/wޯsڰ{^l)./%/&NG//pcW Iu~&,gEj0_1Af0-/ m 0#80/֌/cW'.tD[QD/a,x O@vH0l3,EԮ_%U.-/0נ/Z̯/-j guu/..l3_1j;f9n.:gI/G,,c/D_/.x2,0"EԮ|Y/:gI/_?!/5c./ˑuu0?/%U+0/./5x/S3L="/ .P8i0y0*or %Ұ mΑ/.9n/*/fS20/گyl40k G殎wl-:`40+1QA0݋F e T DEn:`eb0 001t0R:){0{^/0J#/ Ix.-./D$\0b:k .߮5.֯_;P /G-H៰ɰfb,\ZzV՚AfL/.:`e=/mήrwo/ (v+/E.Nyg>//0 {`^0X"./Q,/p_10lZȰl3amίî0ԯa0n-!.0|&mέ)9;0S0!b/|B0(-\/// /@JͰl/l3f e/^:_/8鯻\.){^/gE/(ł1/.lq.tk/`M0JUد݋q/?$ /݋/D-ٙ/E8u0lf0(-.$/ބ06H1!0p/cW/8qN.`/ѯܯ.00g0{^l0./.]0(8u._/OA/(v(v/.ԯ9n/_58uQˑ/:gID //(Zz/'0݋.\fLNl3,,/:b0!/0T'.0x/?0 Gnyl4///:gI1S//~&/pJUylS3L*yl/q/.دî{/n'Gc0a0(:gI/(-QA/+0h/L/=k .S3/D-_ %/:gɭ6 8u0 Eԭ./0.̃=="0/گ?yl4/}]c?0p\A0o&03H 2,_.a鯪/o0f?/X/ /ߣ#D.a^0//5ů0="=/0߯"Qm/Pٯ̼0:gI6>06>D-_̃::eZ0l?0>(5E/9n-/.<)\_ߣ/8u/l-?/3H0Dit0'/м/ 0(.5E/hBߣ"C̃/+/00QA %0[0ˊ!/ "~.:`g0;,՚ :g-:gɮ .D./J#ٯ\|8uބ/*0Z/Я@ˑ,Ԯ .k />y0{/,m/880ѯuu /:gI<ĻL0ze/)/'-/%x.1.v=}9nA/&NG賖:l3/݋Z/ˑ0`ͯ"/t/eZ//:`e/՚0f8ުC/*/,^ 0+@/@JWگu&0՚0C0>(QA/!uHCT/e30 f/_/9n.k /6P_/a.a0A/87x4/70-x060N0.C(v-r30D4d/i2Te/06>/a0VQ0w=f0/֧/ު//̼ 0Y.l/70Z/W"P0oc0 0zeP0`/8/Vɍlm_.()=É.0//'0+q0-H/C xsAL5/([Qx. QA>(k km0401ӯ֧/^:q0xz00`M0~&Ax^X/\S3Lުl="/nj/ѯl3.l3.!bު0 Ư/o/ܮVvު݋/FJ/p/a/i@0`ͯ/gE{^l/Af0ބ/'0ބ/z0/b/ 0k 0/+/-R:.6a0a/ބT,/)0!⯮h/kx0/0 e/S3̯߮D_8[/"eZlf0gE/eZ/C/U/ígEꯡ*S3L/tk⨯*/+Q/?/w! .hB瓰HܯƋ.8.`.u/=//gEj/" ,60D.8u.l0'mNބ0\sL/NsO0l//6-Af0\C(.0{ 0/) }^//e{^쯆5/ 08u0/_//xk m.X/ /R:0/9n-/.l0)0~&0FJ/_.o/9n<)0U"86v /sO50 F~/ {/F10&Nǰ{t0,,xs.,lEԮ="Zhg/j;yl b0140p/m'/ԯv0<-Hl3/v 0#T0I0Z诟fSRa00.a6>'Gl3 C/:`//.a/#0c."0h¯/?ZL//xT.EԮ ^9nмJ00tk eު/cׯ("x.:gɮX9n-龯z.x./AQA_,R:0/l3.5ů0A0. /:gIA/8u4/*/:`8u./S3L/'.+04dX/./м.:gI,D.FJ̃=0"/נ.ïKh:`el3l:g.-ȯ/<ݔa0?.j;Ma/!.(x.:gɯgEj^/:gI-.o&/F"0H1Q*կDE./$*$0<)0D/'}/B0xXj=//hBn/8u.%U+/sO/6%0Cw<0JU/lmήOEے//6>.Q/נد\s/h0x6{/t=l3,x.!b/"~y87x/]0F0x M(v-~/:`e.a/2,Ax/D.Cocy@f4dJS3L/)a6.E.0կ%U+00ު/"0oc//fK' q /5O2[jܯ8uˑ:`./6/.>(/l3/5/A/KUĮ@ïa,1̃0ڻ0/{^l/X0lF/دfS2/{|Y0Dx!0R:/|"$\8s09n:gIg'^r /?!bV]u/(@6J\'}p/R:~&1_-T,h/O'0qRJU 0*/QA {`/֓0!=m$\S3.׾06/%?/FJbj0LGn./x0":g/s0m./y/V$/̃=5\sF10g/̃'g^5/t 0%B~ S3̯A0ˊ!/x/,ؘ(/?/5E/Y'ECj;*$p-կ:g-+q05O0Q/ì018uhB~/?ު.;2*_/ {T,h./H1!0q///Zaa/gEj1ӯدN0/u\E80 20o&oc%0/=a|c0S%0T/)k  I/e0 n0<;$\/rѯ /^笯v <)0"~0QAN0E0fS)r=;E.t/6>Q9/9n-м֓/k É.9n-/|B!b0 /{a0֧KD.د>(E/'_,R:.\8u0c/:gI-QA//݋\/,C 87rp/T.( 0/%U+xs/D!b/^5/l30_x=m/6>/0nj5/ 0Tr0p+\ު.tkߣ#0TͰ?/.Z/Α0ބ/H1!0lj50A=/)/ /l[Q }-I*=0k L(v-H1!Dv/C )/{8G/fS/6/&Nǯpt0>(0nj.دXA06/!"_u_C/nj/6/V$/5QAwFJ$\/ x0R:0eZ>/0?/xzOeZ/Z//Pݽ/\%U/ˊ/0K8u0K08u. 6 T,h[q0߯3H.a/ ,6*3헯>p\/pE/Ar$]'"~:/) (0CʆqL/h).(0'.龮u//'/8u09n.x/Qүl/Y&u`ͯx/KD.4d4/A0R:0/&N/S3./{^l/?%U+0[0) %Uު/E//Z/_.l0/La/ .ު8/(vuu}b0APٯ^0'.a80[# q/`ͮӰp\A F<){^/1/ѯ /q0 0CY/ * 0.*Z/l3-/.T,^͵(ޝ/x_>0'0o*~R.\.=]1Y6;eZ0݋݋T.8u/yl4<)-?M)90=;Cy0|0.ᮇѮłQA/V$0DNy/c׮t 00 /#Jկ.݋A00-ȯnj/cW/800m.nꮱ0(v/{^l/=D .ߣ.60QA]x/,2/QkR:0/0C"FJ/f/f0O0}0.0 eZW©0C.T̃/ٙ/h®mή* 0^qC0.40 x/T0Mq0.ҵˊ!0f8//6 0M06/QA.Q90/򼥯M0EV50/Kw.="0{^l鬲/:0_0L/Q90A毈/(/Q90<Ļ/ɯA:gI"ͯ+ b/.دS3̯MK/|&ҝH0)/鬲:.K%20D,lĢ-V Q#/-'GoLg0/i[;EK4?ͯˑ09n/_xsy/F1R:00i0(/ 0n.-/0@J1="./(0{+/Z/:gɭjTk S0FJ.O@//[C0n0{1/Z0\C?QAeZ/ IMˮˑ'賖/;0X\.xs/yl.g/5./a^3ÉT/Z/8/!$0:`Zz/(@06-:`e8/V/ZQA/./̃+00֧/t/M0'/+/ѯ{Њ//7 0="zeP{/(DAA.1Ӯ_../eZįf08C /5/qm 0_->(k @S0 )0*ˑa>cׯǛW0aޯҵ.!/߯%0j "M$/Ѯ'0$\/߶.0cy0қpL/0?M0ѯainXl3/K1Ae$\C>mI 01Kఝۧ01v/\ p0OE80O0Xss0`M:`e0zeP/(֧/ 0001|0=(@0Fʮj #-S3L/DpدDު/|B:gIQlNyg/i0*o賖0'خ:`eMR050s1'O/w#g0݋(]دvH0/Inj0ߣ.X//P/(-﩮>0=]0"'ή0Ny/h/l3-_On5/+0"l,0/R:0D'0ˊC/Α/60eZ/ (/E_o*V^/_<)P߯ '̼ 0-R:0♋߶vM\|0.\/=װZz$mNÉ/cprѯ_Gf/.1-0?X֌/_/"'0QA/̃//F0xs/?M_1/G򼥯{:`="0V$ۮ .6.R:.ew0q>(S3L;!⯴r3/sO/֓*T,/+"'QAhB]9n-j;/G80l./:/u/֧v¯a,0/C0ˊ/ /N녰_30AZL/Ic 0y0ҵc/0/e/(y/4OSl0R:0.{;-&NǮު0/= 0*կORL/x_ـ0y*0$\0 ,//+5Q}^ł/t|/0͈0T,hSK0qU/ {/8&Nǯ9n/!3q0"0!1=Wh)0L 0 7 "+0.|'_/°T,-Cs5.5rZo̘<Ļ/000j!T0Qk/-Hk +.݋.ٙY I//ڭ %*$0 .1K0n-6 /~xK/{@0-/rĥ/:gɮ錯qNy="T,h.ŧw̃T,h暯yl)į2^ ~zQ.eZ X0K=R:08uNyg/J\>(.:.R!=^Ny[-`0C/^:O/,\/|ɦ.c._/5.S3̮Z&Nǯ&N/:b0a^/8/$\/~z/XtkF0Eے8.n-ai.r/j.ML/"/ss06.'G. l3/ï%U+//!".a0S/M0Zh1S/EےG殸q.D8/5D_)r3/_.]/'Gc/06>(-[Q/>xÉ/C 0~&z0fS\.^`ͯ.0-Ȯ/t08u^/{^S3L.E.0/%kw/l,QAmήE./O/4V/0WV0(m/:/|/D&!0E0&NG0U0 /Ϛ0:gɭ`M//^:]<ۯ)tZ̯EC Я}ޯ|B0/V 40 (0.:gɮhB0Q90/e/h/ {`/(vi0.l0%)0x/v .Ta88/A./'}+/ V/Α/.0AL5׾/ 70(,=.eZ/D.GJ/|&.,?0>//ai0\0!./<)A/:O0`M/`ͯEԮlÉt 0)Cq/T_3Gf/]08/]j0֧-D/R://./֧.(v:gɮ47_נ/t/QAl3Hܯl,Sd6>/X60+0//~&/ Ʈn._-"0.,,06>. /Eے/eZ0!b/D-[/ٙ+0:g/qqNyl06R:0;˟/x/v6-x/.ٙ6X,/ /I*=="/yl4د4dk 0S3L/Ŵ (\s/]0~\CVɍ0mN:`e/= 0Te70{5Q/v /v ҵ./?8/Af0l,mN._01S0?q(/j;/C /"~o..l-(5E/9n- 0yl4/QA//x(T/8uˑנ/ު/6>.+yl/?.? %/j;/<_گ| /_ۭ%/߭ 0K0'[QALFʯ %sJ'.Ͱ %/ߣ.fLNX/݋X:/ҵ/vHR:.n/X0(v="0l3[#8oc%ԯq4d0A/Yhnj.-Qu6>/\H/_10x._//ˑˊ!0\/߯k /l2,0q0ůV)0l3>0X/߯[0:`9n-0l3,^/ïnꮤ_~R/R6J /~&/&N/C/CXٙ!. %/ {/ˊ!876.[/0WV0/"~= ,,87(vl3,C 0Vҵ.b#0|0/گB~ J\0U"0C8u_18u*/Q(/1S/a֧//Y/~&Q90L/0A߶./~үQAA:06/x//龯R:/MXϯů1l)N/A-ߣ#\C? G8/-JկK//^:h. /w/?!./.+ /9nS0좚0ߣ#/ /xC00o/ì0q0w^0v/.AK' 0OnHܯ]<ۯ߮Z`0^E.Y0.̃=_/) R:0~& %/87=ׯg{9RaCI0گήDb#/-t.o~f/;݋+/?/HѯZ>8u=0ƯX.o0+/ 0"~u$\/).s0-an/h/hB_.ٙ0q/p?0?ޯZ.Qu|'0hwկ[fS/5D6//ͯ?!k l30e{/u\Vj\b/0ѯ,,:p/C/\| .xs. 0"~/I*=c//yl4/ު0Ku/0.a/./ ..J#/S/*o:/4/eZ0-DK0 //(/$aXٙY& .w/`M6>/e/̠02-l0#$\.Xv.+rnj 8$0 /0暯.O@0_o/Wگ::`e)a0h/k p.2,_1$\T,h8Qy3e0\/π0 /!.Eے/ߣ/8u-_/v 8s06>x/t|/Xl-m%ܯO!/)D{^l/$\q.QA: 0/^n@J/rήDD.8C/K/3E8/6>(/L/01/0 Ʈc׮Jկ5(0.yl.$ ̼ 0Xנ.?/ .. .m/É/^8iZ /؈0Y/"'0#1o-H/[Q[Q0H/V$`#ˆ!0/A.R:0.< 0MKxs. F.t/]0m/Ao/'߬R:0/ۮ'.Z/J#ٯ6>.ބ.xs01l0o0 00S/ɯnj4\J~R//گ/Iί"/8_4䯷x/5.>/" 0S/u/n0)/` 0e///d/{./Zh+0c/D %Rů/lf0kD0<0D,4/ t{^//.])Kg0,8?N/_1cf0`Ҝ?/Ѥ/N/2,/ 0쯞'D/%U+/o HDt-ˆ/6/*// '8.e0_///ϧ`0r/5k /JF/Q6J 0/(/$p3H=/8ꕯTe7.-ӌ/F0KC>/p/ W/q.0W/>7C&ů6 0[.% F..K0 /Q.ͯŴ.A./1AcV֕K17/8.(0fS'x.\C?+0Q9?!.0O/l00(^.j;.C0"0/C/O}.5.Pٯ:b/*mNů) /' 0a^/ >004/gEj\:gIakүrѯ86>.݋>(h0/L */i/k ̃D.X.4O_8u>(/tK0.a/[/gԮa8h¯3ȯ7p0x= {/K1S3L0*o/2,uy3eg0:gI. I0D 8u/E.00#8/[/T,设+ / /(@/Z.D:*/@S)/D,WZ0/,X/xs/h0گ?A F54/S3. e/_-pD.]0/_,hB/ 0k 0/گc._|'3ȯJU/+/دT,hߣ/0x8u.a..lS*./c׮"'/:gI;0:`eQA..a^/9n-X+/9n-2,0 F0ïfS/<8u /j//گx/Z5'}/0) /(2,)ު/+.cl.8u.<)n.c~ү?!l,T,h-a{^`Mst|9n-/{^/*U0 :`e.ԯH*Ey50̃QA/!`0\.R:.AF >*կ=/˯\s6m/k /l//ߣ#/tį:gI8i/Z/./%d[/^09n-./.="/.ˑ&/{ 06.9.z00Ua5ZzC|b fBEQ01ӯ>ԯk ./~&/AF e:gI+6װ/ĥ5dm_u0 ^!4 <;!1q/$pE((1/ބ/>( /+/ F$/9n-/0 Fnj/Eے/+/./ {]/50{^(u0//A.a2C0}0/É.y0!0S^n/1/ oc%0j /0_10 /y>V0(ˊ0WV/V$/e/vMG|dey/q*0Cq/BF0&N.OMip/ į/o& %/\Cc0fLN0!1n.5/(0 /h//S3L0}/3~M} j;.EkL0.c/]0< 0\/{/fLί-*K/.9n-0j|@0VWo0MRiK0WZ0Z/8/u.C%U+E0O {`z/ӯ*0k qU]g/:gI-! QACwׇ/k .] 00Q.b#/"Zj"0a B~8/1//i[0/>(0c׮f.W"Pծ/;Pg!b/̃=QAn꯻\sZ0]88u/"0/$ X.^R:0SK0_jܯg/,l+ۮz./z.Hܯq/>0$/Cq//|Y/f0Q950y%0:gɯ~&V0ůc/^p\A/Nyg04߶/Α">/Ցد\0G/r3_/ipq/0;҃>60R:0.v0/Z1ScW/H/N_1E.֌L7C&H1E0&&ra8:`/n0x0/Z//A t:gɮŞ/T,hY//|'߬݋./~0w#0 ,/= 7C/L/@//wޯ./=/T040Z*o:gIw0Y&8u=":gID/.a//..ᯪaޯԮ %үo(-v 0JU0gEj&N/2SK#/~&/(- (20\s/Z-:gIA/g0m/GA毞.(/ڮ=-0S/Q/<0xs009n-|¯qˊ!f/k --HR:\E./l3.EԮ06>.uC]R:07 0 ɯ 0/\C//Z0֓006k ,a/M;.p.*/נ.6>0ٙ/y/_𢯆ԍW)[j;.|'ު/';~ү%}0ѫ0.Q0/ZL/N0/D0;060ϯc6.c0/ 00A/&NG0B~ 0^0XvV݋V )/j0ԭn_1/9n-<;0j;/r/'Gc4G80ȯ0W/z/sʯ1ӯ/ބ/T08u0}^0:gɯG/?0AQA֌̯yl.+vH0_f,n-ˊ!m.,՚:`l3*0qx ./ + Ʈ/(,DsO/y/B_10l-/0ze/O0{^l/L+0(vv/<ˑ/7p0xs/AF0. 0Dҵ/:gI-.o& ,60l30~&01ӯT,E8D*0'0֧j\0!,.t/M/yl4/ 0xs/_0tk0"~/T,h֧ D/|ɦ//گCR:w8ҵ.ImAT/.ٙ/p.xs~Rl3.֧- /[Q.c/_'G/QADpدV$/-/%\00\s.,\0F10נ/J#/נ'/L/0@/נT,X/T,/6J 0eZ߶/mNQA00,,///eqN/?/'0 0~&0:0կrl3H/XŰ̼ g0J0vzeP0P0y50+/C /xCM-0`Ͱ偰rʰ0ԯ[/]u"l/C(X{^l//*0e0QA.O0r0Tҵ..6ai/_/T ;0q/:gI//0l3.l,F10C0xs":/u&'Gc׹rq4,00>TSl3. {`Hܯl3 D/p.-.k /Z0/ai/_0a^/:`e0zeP//Eg/) Y?J0/Jn0fS2/rYZ/Nyg:0ԅ0:gɯDOR0/0l30v/_0ł0&200q0J/V$/c/BJ/t0߮-H.k Ưv0A/X9n-l3-6>J\(s"_(N/}K/3T"//M/k=0ǔ笯//Gh/2Zȯg(rY 9n-x.ު*0h$0,/DD(..C|ٯcW/[8Y偯FʯdG>ԯ/įB10/%/Axkǒa_mN.}^/ G0H._/p/+-&N.0-u"נ-Уf/JE0Iw4*$0\J#.fLί4/oY՚V)/`` W=VWo0/6> 0S3L/.F.Ax9?0ǭEC0V$3ȯ*.l/_gbh/S!bҵ/-||ׯUï/^Z:`-_9n*oB~ /8ѫ ,6/-/+xˑ.//O.g~9 м{/JN̯O//_/c0>/м|Y.k0=>(:`-*0oyHQ&T,譬kDy\s.̼/E߯$6>.I/&.[80O/`X8u.Eے/43-c/ˊ!0Ml֟83 04.wA//H1P/8u,HCc>1Pr-xQAAFgJ#ٯ|Y/)/v 8*o.=-/{a0N,/.gگ\0T/ު.BFS4.mN-..'T0fS/8i/Y&/׾k D/.㯧JU/߮@S/T07 W0s/5EY (ί[(@r /%k<Ļ/b$Et00 ˯火P=үq`M̃/?ͯg0.D0S/50.0Q[Q/'.y3p\A0мiI0D/e,,-.l/-/@S/?0/ڭ6;/QA/ ߶T,h.+<0-O0tk/O!/|&.)/:gI*0..B~/0O/JU,J0r/l,/=6rKl,ylS3̮:gI/EԮ/Q8.-f|iMR0ު1.߯8.fLN +/򼥯B~sv~}ޯT//.W[o.0a௯Y&T,hr3Qk1 mT0Q./Zl3o/#10/X+ 0 4yl40ˑ/:/`0-0qH0/cW/1?/\ eDpX//!b.kG0@z0D.h0nj/g0+k /Y&0%/Gf08j\//w^/n.v /En.֧.8".<)0*龮h$0 `/F1//"~F040|s0/Ke/Ax .0 ϧ`0=0+/5ů{^ߣ#/QA0Z/H\֯[/݋-5E ^.330W/̃=o&60c׮/KX/h0$\/0fS2/m0% (0E.Q ?4.S3L//X0<)/T,#eZ}0Qm/ï9n-/_/)/eZR:.=".\.`ˑ/kG0֧j;/tԯ(v-(vh.&/5.5 -/Kv "~QA!/8//S0yl/n/*n.hxsT݋6>;//^.5E /ۮz*o/./'/q/՚ 0S3/0l3+uu/H0?/:gI.Eے/ %/\!b/k xsD\s/6._) `+./p/o0D/.cxs 6.x`M//D,!/X9n-8?l-'9n-//Z9n/"~03!0 %0CD:gI/rk l3"/9n-0$\=" F'/_{6.zeP0_.QA0`0D0/Z0Q0mN0T/l.?/?S3̯U5E ư/݋v Ѱ9n-C:gI0{0߮q0:`e1C0xs1j,,y1z1\&NG17lg 0X0S980笯IMvBBF/@G0Trl3xs!/ 50۴0)0݋P @//9.zaU1AQ/Ya0݋-i෯?~z0_/0Q90߮/v/É01S,\C8u0//A0o/_.C0 {`/4Zkma:gɮ`M/380)/00^H043A01/lsʰ0- 1 )g00uð]/^nr3F/N˯m-߯HCGfr.Eے0\X00{^쯆5._/>BXJ#//T/R:./S|0#80_C?Q9/Cq0?M 00 :gI087?SmN;˟EC0'/{^l/00R:0K20a0{[Q0S/x.-G/"~)4p. ="l9n-(暯//-"/a0u뷯~.G80a,<)-0~үnjWZ~үJU/*o/.lZ)/F_0TJÉ/frXv笯1P?0a^.y/p?0ˑ/d0)/sJ,xﯧ$;3HU.{0/t0 nyl.5 ;҃/qNV./\.1ˊ /ު/|-h/?0:/5P0=/WOүl/_*|-Ny/7Ll3-ٰoծ.(0Fc0 F0/'0ˊ;/ 0/ /X.50Z/{Њ/#0aޮήD0 40\| yư)/I"/휢0ht0ڰOPz0c]M95ޮzm/nj,.|!05H2Nx08u/"0_|[Q4ʾT0vx$00J#Y7J%0.X0|/w .s/ԭp%JD.?// 0R[ܬ°ؕ7vr0wq/@ (@ARj;R:07D0{0l^0W/..K0/uV0c60 %.z/ /(/h_#50|C 0F10/eZ/L{i/2|')/Z.!b.t| 0{;eZ!tTei/%[0鬲.5-}ȯ /ήį[T̺4JF.m/-/ˊ!QgJ#/..a.=KV0>D#0,yl,t/W/CI)0.?/:g-"l30Cw/gG7 .c=j0.]P0_ گg߯SZܬ/ 0f/$- a|/,&0Wc/_/#..imί/f//PHZ.?!/]].d(/ .ϯ~ɯwڢ/0:gɬAFv.l0hBs/t0E0O@v.2,[. -Tq߮ &LP/ 9/R0bT/֌Lބ!0X 0fD:gI{/ׅ-H/sJ/&˭l?/V`/y / 050X/L/fc/mN f+/2/-.@J"0Hܯ̘?.pJ0(/-蠰49j.coK0c+qȯgZҰeZI0wS3-=\0Bu0D\C?)/Я|/h/&Qt/#1`ͮS0Xۮ) YZHS3L/ O10&40ylj/;/~&.:gɮ. /@J40.a~0mѓ050_ـ0i::gI/6%0LY0,لO䡯O/(D/0WV9n "]c`_vx$)2貎e!ǯ{Nh-UZh?hB}`M#0t|/:`T/'0ƽ/};҃+P!`..X$0tK0r/?!&//0xo"/. f_0w{t0S0/[0F0(v6qai/&OO/vv̯𑞯ٰo)0jxs..W0C0CخhC0 T0cpˊ!.<)?-y(0:oW)m8/e0t/-d(<0q\k -Ģ|/ު+6g鬲ÉGJ/%Qk/rF/#0#ԯV.?QAc>09#0دG8F8u.̼/\C?/gEj]<[$//L.x0(t0͵m0-/S0(mV006>/Sl0< 0U:/E_0o/߮ %R0:/v/D'0\s0\J<0430ބ8i/,0BŮb/ꯅ. F.V$l30:`e/|ɦ0ߣ/njN.0LN`3/֓0.Zz/?/.]<[pG8m/KZz/.lO!nꬦ0̃=95^1֧/_/j/̃=nj S䯛O0:gɮk C~R=/42hί /̼2.mήC ֓0/W-{/:g-O/,.a/_/.l3D0fPݽ/Z.dl%/ބRh-)V /U"0="/ł<)/o Cz"~Pd(03#k .{Њ/a // %/Cߣ#.//s0!b/Wc?00ǭ/l.3~/Te00Gf/׾70K/0;0[՚/+/%0#T0c>/Vd0fCq/!b0*/Ig{^˯m/U/-ȯ/Z/&6U"i@0/d[ҵބ/:gɬx./Z.l<0M/ .Do/ /FJR:0/ wn-S+._/ T,h0l-C0|/ 6݋-U0L-y/rQ9//#0xs0*/6 0(@/(@0i//V$/3oSl/zeP//~&x/ X/o,,.3S0t/vrگB/tkr/gEꮵJ0gE/\//V$a0 ՚2-M= r並/R:0//Qk)|/0//{^쯮˲/ /ήĮߦ/% dG0 p0R80d/H/40{^/賖/נ I(>+02/֓0/10N0?,\/.c0J\(o0Z.//A &˯q/o&/j;~I*/F08/lm=0f/g00/ Ů'G㯠T-c/M0:./ 0".t :⯈6 /aKA'G.?QA nj݋D2R:L-[Q0}Ir/[Af7/mu1K//"010!fU"0:650bT00.خ\|/(]/-/S/1QA/݋./eXo&M-_lt/hnj נH12V{^lx..yl/)r'}²08u.../HV/̃=0Y0:`.|W007G0qW0GiK0&*/fc voh /|Yi0J#ٯr/O!0m.N0ðR T,>@ʯA#)10e0;/-Gf.+ ί(V/6>0;Z03/|0.//8.5𮌅.aX W=/ :`寃 an/gw/(v.D: ( / =W/"ïz1PrU"00r/Qa=".=w/\>B?!.<)֧xs/*/ï.lͰGB~/ e0-k /!b.R:. ,6/k /:`/)y@/݋߯b//3H/Я:/00ei0G00 0v0F/՚tk/Ђ0'/D`M0"/l/S3̮ {/#8/xP0$o&uM4/0֧/xV1lk 0 //9./t/ ,./ T R:0/|ٯ.n:g,- /u/xX//-.<)!{a./e09n-/:`e/0/\Z=.+|0t0.c<~&ٙ.Z/T.q/<)0.nj/ׅh]/qУ/T,h:gI-)暯Aa^T,hD/Q6/(v,x. PY_MK]nnjׅ8u.(DSK0 ބ 0 /@0*o-ȯl?0hA/QA.l0/i@0 a/9n-~&Ci7vsZ0 m0_3S3.ei03Ȯ/[-0/6 pţWe/o6>00wA-/2[80'0T/j g4D.HC$ÙPY/78i/.0M/0O//(/y"ǹ/>X%0O@0O/+.̏.a fqĒנ.g/| //X̃.0fL/9n /]y0:/^0:gI/_.B~ 0-(/C. 0鬲/6k0&d0X/\/q_՚/#ԯEr0qkD0W/֓0/o/0q|/7G0:q0e/x-./|s'G/6>-r30X0 k/].f/p#rx.yl4;$0{/h­ԯ=]<ۯ:87/P"4'1S/g/ F~k/4/Rډt/t g߮.(/U0$ ./]d/t j/+0/8<¯r3Dǚ1S3̭ίDpخ/0x /10\s./=$Q۴0VCM/h/Gf@/P0A.~m90|/6:9/k݃/ F0%/kmV>8u/=.-*ۭ(qU]Qu0,gEj/#10l3.]|ɦ F/(/..) .&.Ir01֧(ɰ(\|0{3.ѫ/|/0@0M0!05MG/Բ0W/,0ri@/.ԮR:=//ۭ+@P/:/*=/=0&NǮ:gɬyl4.X6//Z/胰@/ x0A6ׯ.'0/](/6>.:``8/$\<ĻS%0./{/%\"/s0Sd08_/< .l005///D. 0(/:|Wm.Ny0n.l3pnj-߮mή/Y090\0d//-xs\s/.O0X5\/02k /(= gE)0wޯQu:gIWZ0K֯.ll3r0N09nު/?g;yl/:gI0R:.+8.{0t 0 F.f0-:0O/ /݋t7L0F 0ٙ\|0!`0^5Cq08u/n/x.0دw/6>hB//q0I0c/z..T,诇)ߣ.%+a*oR1tip .C/hwU0:`e/c? nb0=o//~05.j. /c/4Vɍ/Rq'~#RB0akq/v/9n-gEz7/AfDpXi;|/5/p%0U,7>R/x/->s_./ /z$mѓ#08>()K9/0͵nO0/G/&.0DB00,!0(0\㘯 0./~/[/.3/a^.$/a^//؍c/*o/BF%O//3/֌-|///0cG0 e/T-u;O*:gɮЯ1/u.ԉ%f/*o^-C.׹앯30Z.s랯A/U/خJ0Hܯ{ /?T0&2/XE8݇0?M0A/(atS0LOүn6RqQ/%02[0S,6)/ٙ+T/^ތK' 0]/Ԯe#0ƗUdy0 %/8/ˑ|YطS0𢮘/Zh/?0L 0r30إ0@0!f/ "]//*0 {/ª/!-n0{(+J*0./6>ˑP ACѯ$ /d[p#rfLN.YG4P=0>/IL/{ҵ^.H/9n-.M087.V8u󆚯d(+{/6qa^5w40%U+0c/?/5R:0կ/F0x/c50!a00/P4do&֓0//.'Pݽ/zeP0:`/T0|b/AM!fSz.O?t鬲xs06/;P//&O0E8?.$\.B[4?-i/jDk݃030l+5.fLNoZ(v0$/Smb/}Ěˑm7eQ/ˑ.X0!/AC$\n7 W0A.+,\"0_/z0/T06:+0K0a0 0:4.*4.k/_/+/ɖ0\0R:_̼ 0q-..㮒?/8P080l3TF/}A)eZ9eqaޯ& xz/1AQeZ#10Xp\/_ì(v e0:`A_r30'0FJ/mN/hB/Sѯ /N녯kG*ì-V>5E,1PDhBٙ6>S3̮3H/z.0:`9n- 0="'/hB/{^l/)06%)K0P0/\a/"//:gI-j.p/sO0D/)C. 9n-.\0 ,/0!/(t0Z-0/ P0΂)0Q0~&G e0M0fLN~&0aiP"H0 įP 0ut`ͯ:/n/ u&00j۫/_6>-/x&/.lPݽR:0.>ܯ0X.D.gZ01P/./Z-X/{ЊewAF0'0/ڮ}0/j;>X%mk 0T.&d{^/EԮ/|/D.+/V/s';Z0aF^nF0q// p.0"'0.2,J0|ɦ37 /O0(tx/NG.ze/{0Z-_.{^쮺<0cW.r0~wA-,9+נ/9֣0D,G8٠Ǚ//ˑ1/Z.9n0ODH?0&0P./0?.cp0"n.֧,{ 30dy鬲Z/5J/U^/K1Ƣ0hwU[Q0)Bׯ.7 R:/fSyl4N65.ٙ/+0-0̃=/'Gm-MCq/ˑr0K0!f0eZ0V>00 G.Р| 떰Kj /{ Z0BEQ0u0+/J21fS/]xs"10/Tm}W/(@/20t,Ѵ0e0F0/K/'Q0 11K0<;0eA/80R0ZT,h_Fʮ:`-5ְY0/xzL+0$­O/3.(v/00t0C00/0(b#0U&p0 %Ү (//9n-v/u&/P/\C?\J/?Mq /\C/_Zh?MTe7"0/qHC_ـg0oKg/|>(/.d(+ߣa$x/ު*o/sϯ./D0JUC('/ ,604d/jߣ# FU0(v/|W0W)0ˊ/K0_D0Te70zeP /Eے.d(+l3/E06;0i0/A03H$\&3.S/{Њ/T,h.ܯj۫/*/u//0v Ϛ аk /֯%/(/430ˑ0.Cb8pX/7 ׯ/|ٯ /{ 0Ar3/fX0Dp/f/נXsRGfewU.|/b0ˊ!08i0ʯ!f0' 0o P0N/CHQJ/:`e.!b.B~.$ S3̮]k \J#/ǭ.= (yίCwaޮzeP/ tSZ.ƢHïxsj۫DZ̯LF:gI.AF..="[8Q9/;˟_1.jY&0b50mD *կ@Jݰ.c.4 %#0 ./:oX /O0/..QAYh/ì/+.. _0w0/10 %/R[03o0ϧ/P 0௯/>~/y*0wA-037`0\]0,/eiZ|ɦ.zeЯ|.{-\"j//(@/ В0k;Rm0 0&ѯUAp篷BEѯ0XT;0G60Y/-z/b${1A0Ysʯ7 W/}ޯ_!錯*݋.T-T0jT080A00/"5X6r\&Q2ܯ4jqݯtk.fخg~+۰?. 00m-I/DB05Ů#/$ %//<00t0.c/_0kD0R 0kD0`L/G6-050/3[/2\/..㮺}l3?4/Y&/sF0/8P/A0G50K՚/ ԕ.ى{0ᯔ0 0笯'/6;0(@/L/V//._30/"v00P/f'0 .<.Ku0I*/'.AFyl4.*=6/F6~.R]<[.5s0I 0l/i0X.O@0P/:ު.=/w&06Cdy//D"~x נ.훶;0ize- `zeP.5:04/z.ׯ -0$ .]/Α-/10`M.AƯ ,6g0"_.>ԮFJ. e߬rѯ 𑞯/Z87/>/_.sϯު/F+.K\C?/^/E/cW/A/<0x_/A/⨯ /ܓyi8'.ȯ.R_/᯵-:gI.-//k /R/|B/E(/(v.60z1/J/h-0ìMK.l.bNS*0\d0y/F/&,/P0x:/՚0-H/ .3T0AmE20:b/i@/5 0.cyl.c8s/įV$'}a.ͮnV0(@0"0)00x 0,0/".u/\-/`#0xsϳ/Կ/q/Ϊ/) 0%Kv ߣ8>i,/H/x.,O|.Ȕ95l1G50w0ڻ_./֧.xłsʯŴ/m.I*=y0l3S/p/00y3Ax-ݯ:{zeP`y50ˑ/:gInCR:/J<0|)M4<8u.3/0R0mή2,/A0VWo0..;P0k uu//Ny/CI0@J,/.Cw0ު0:`/?00R:0{ .AD瓯!bX rD,D^!9n-.Y&.;˟yl4/%1ӯ:`e"~="錯"0"/ì0n_0I*/6MK/K߯nj߯(Q90̃=5/T/!tD-U/q/[Q/Xxs..R:0{^_%U+p\A W=0;˟30W/`ͯ/F-fLN/X0 0J\QA~0)/0W/p/֧-/ߣԅ/g0Ltk/D'៰x/)Z0ܯ1l0ipq/j۫A0k),>OiA05pi0"-o80J/g)"~^CE8/}׎$y/Tʰ_Vɍ/݋/l3+ F.BEQ0|Y %.zeP.rY 0/5hB/خmٺ5㷯G8 .'U21-ӌ0 F0T,. 0[QU0Fʭ^5/tv06/oc/./A0~RjήD0T,讬.!b./Z/8y/ze.T^"/?/-̃_/m/h_/fSDhB\C/-H0u/ 0*ogEjl3,J0/e/?^.c/]3\sS3̯/k/+ A殿(@//Z0 FGf`M((0JUd;0?c/0:gI/va^0/D/Z/-kD-x̃{ /n1:/`MqU/m8c/P=06>,ϧ/m/_/0~&-:9@S/\J/3/".oc.nai/bT0-H/0;0/w/T,خPY$ .uM0/Mhdǯ\ȯ} ("0ڻQ /Q t亯ĥ5j;/zeP/l3h$0iKg}0DitWҵԯsʭ+.I0D/lf/R(-Nyg8u/.nj/ӯBy. oc%. D4v0E////]/8S/ {௘/.3= 0{;(&20k -j;0BE/LfLί>/Ŵ..X?0loMG)/(0A/Eے./ڭP:`eH1Z̯N녯呰X.p/A06H1!.S0h-?/5Er/R:G0AL50h/ %J#ٯǭ/L/)/JU0$0"~0 Яׅ/J20м.ˊ!/l\J#j/"~.QA/Y0 /!Ģ/vH/l3/XOpm:gI,"~-u/V/U^Sxsr3Y0j/Ciæ05xůk d/Ck .t_//;aѯNIl q?G՚0q0]c0.0îˊ!/q/W0x:IMAf, 0_ـ.㮞1Pr/0~R//O䡯;+/}^/ˑ/'-ˑ/Y05Y&/!0<Ļ/b/X0 p0rd W=0.l/o/Lм~&/?/(v֌/Z"/Y/S3̯ ="0a/|0i0J#U"/ 0o 0{^}^0mN/í0ڻO/zeP>.+g0C !⮅ٙ:̘/ 0R/3/!0QA0FJ/R/XO0/_/8u.-/ҵ.*$D.?_ܭV 0/:gI.g* /CI0]Ư.Mu&[q//A0z:gI<Ļ/ˊ!.1MK/9n-yH/2..9n/ʆM?W8.f w/];0C/h vBQ/5?v/ Izg/0n/i̼ś/X0?]0 0B09nY0 ,60=]100E2/;1 /0C/"/Np0$\/Q/n/(.a/~k0K/ҵ.6/lfTe/FJߣ."N.,O0 30mѓ/(䤯/60\-,h/e!Gnj WZ.njj:gɮPzY)tAJ#Yk !'Gxs/|b.06k .}\/ͮϯ00g/?/ Э֌L0C.!஽Y?0Y.0FJ.&d0"0{70>. 7 /n/$#x(.0<Zz.q-`#%MA௯{ /暮n/n+=;[/A X03.N-HQ 0\|01/F/м((o0 /U6>}ޮ<Ļ~I! ,6/ %0Dit%05.Zz/eZoK0:t0ҵ.՚/ł/5_-m80/.c.;˟/vG%Z0@J04H/"-_0P/ //5߭|Pٮ.ˑ0"' 0/(/+/ߣ#A/sR)0мT.Q0j"0TΙ0݋/l 0A06>-/Z/0>0/1Ӯ8u/L/ު/"./Eے.y/S˯Y;/r0{ 0W/k />|B/'-<̘)9mN.T-\/xs3H66:0E0Gf/tkQAZa0ï@/ ۴1Ӯ!ή0@Je 0 /k -;0b#a.\ p { P9.8 v0! 0廯,D]GX6/P0/-eZҝȯ\C?/k4>s/ͬ/t/;0k/~//[-0c/0Y/~/,?/ -qO䡯 0կ4d../ҭ/X/K00_0.ݮ/ /0 0\ %0ٙ0/.8/1/xs֧*55}/S|]>0ZO/Tnjί ūAX/km^/{_X7/]l/?!&/Z8<-iIXϯ5Ů$ICw<~.$zjB/j{/:0E/=İ[0."/qs.& 0 /05ů,Gf/ׇ/^/XDeZi.F胯KU.050=pJ-..Cxt|C-]L0!y0x#8M/$֌̯]%0Z.T,hoc%0D.ï &{ia/M~I'0x>1?/k/r/a˸/~#04,y/'-80ze/|/J\(X/!/۰}ìR rC) /_3/P{-j;Gg,0J0006;/Rډ02,/ %C /9n-/(0VW/R[0\J/ҵ/; 0n&NǮ~0+G0 />ԯ95ޯ 0ocr.ï-H.ӯ ЯٰM|\s/:gI/OR0$0hB0O,..J#/ F0Rax֌̯pc/Ű̘m/eZM/!.먒Ym8u&?.̘/K/ZW)/./njx0"00폯~/{010lm=0/%_N0./.y5//(]0؇/X0j/L 0*/g!/RM  \ og~zZ//x.\ /Α/R07_o&/2.4/@6`0Eے/_O@/:gɭY 0.~)- /(Z z:.̨/0P/0 %/!$!偯 02,/F/phB/uî\oM1˯q"k0ZB0;>®g/c0=W.ơ/@/"//mK/A5fU eު/Fc/)K 0y_.7s90.u*Te/j/j{0X02.T,/.g/vBׅh0mI*/H1\|.k $#נ/EtS3-Y&NzS/(N0/Q.c//g/*ծiIlQر/<;xoH/dۮD N0Ug0L/\10Ya//95^00Oٙ.q//C0N6z/v0HELw/? /0t/&K00F/G.0*0zeP.hۯįD/l/Y0/ꍯMSzSބ..C 0^NPA=0]]/e0֧ / Я+/'|b0FJ Dq0tkr0-暯 01S/106/)䈯%U+/[x:I/#T/#04d/_߯}( %/c//h0b$.'Gvr~60ߣ/ˑ.&ѯo&.8 /=i{el3/0'/k݃nꕰC tkAx/賖eˑ0:g-3/ٙ./6 >B0K0K0S0QA.j./P)0xs/~/F0O'0W./%ܯc/0(@߶//e0>xsO/-q80_03q0p0~ɯeZ/uu(/v/@/*0{//A0+0V0M ՚$ÙG/&C4/g0/.ql/8u/DT.j"\s:0ى0/7 / mN.>(G %ѮIB~ 0/;] (/gEj/l+/.\/ai/2O00nj߬.l/yl40_/{/8/É/A/DIc|ٯL//mU"tł/$ /;0Y&֧נDpد-Ta0~Xv/o/E;SˮO//0_/hd nj.o.Ea/ e3~x/Bϯa/yZ-H/@/ ..t [x^0Yk .֌/ܮ.10:0/.ar360nx/8G0w//"< Ư( ~I/xzi. /H1/BV0w0E/Qkz/_/ܦW/ //k NٙĖ0DzeP/Nyg/18/@/Ůt/D /~g0//3) 0M/l0+/* b%/Kڂ/h\Z/6> ߯^f/:gɮ?wA/'^/м.ڂ40HR/0I /0AOEԮ-QK0,p/0G8090Q9/b0.D/O<0Eےήį .z.+/Ϭ0 Po-k 0/?.IBw0:gI/q0ECП08t 0SC0V #lj;!ͱ/<60jiK0Ѥ(0F03&00BGq/ˑ6i/30. j0-//[0E8/&N/r/~&0./Z./ZL!/vԍ/Zh.^Eb1ӯ+/<+F0U0r0gEaE(@/.瓯 F寪/#/м/?/m/Z/Α/|lX600 Я/]j/l*mή߶/\.'Gc/t 0Cj;/n-$\="/Gf/$#@}ɯ~0/>0ʯ3HƢkaޯ'ï/گG8/,,n0AƯ<07C&a/'203G06g{/!:6>)į^5?ͯsZN0׵/Fֆ0(215S0O㙰+0/"t0-/֯; 06nj 0n`$*/[-aE0h$C 0rCI0}ޮFίL5]E!\J#.)D?-p\/_)/mN/b/a0).k .ȶ/r3/Ǚ/1A/6/$ɯpY/`#0賖.D =O'//liKo&fS.$/9n- -0.a -m.uïv08շhv鯸0y/k ,Q9/)(@.]+0 ^.)8u8qF{BEѯ F.B/ >dۯ ɯ^M%Q/j/"M.&x0 $?!՚+6 ĮCHV0&x/nͫtl0-QL/t|Ϊd(Sr=XtK.߯F^0W0 //AL/ {`U0/M=]AfBO// /m/Qk._<0mN-㒧//lfG殜H*5/,\D/9n-aiN/k#0*U/CI?!.Ư/l?//&/n0[0|/~z0/^/^nƯ/) {80( .>(/g{&Nǯ:b/6>JU/LN /(v/Z.uCRډ7Mq._/׹ F.[0`/0C F|-/q0a/p\j/rQN.0%/鬲/L/ۮ/6//^:. P/$/'0f'0xC:`//ڭl)}/ALyl45ĥ¨鯖دBO2T,hw#D0"~/7 ׯ&0MI/cW/1Zn/0`cQ/a_0qo0ip".r0͆iz/͡#8/O@/c]0d(rd0fQ]e0t~/߮胃zv/׾..A/0 0/^.WZ0򼥯&0|/n/"~/b/z/j;/Xxw/FJ..6:`宑.F..!/)/dG/s Fkݯ|rge*k﯇r0!70忆/*K^Lհ;36/0et@#0&KMG|\/Q@#b0՞ڰd/gEj/֗/$ "~V*.<=&/nj-u-Eے/ɽht:0|&bf0(ݯ௯SdGϢ/R5P008304/)D/0{e&׾7N/#0cȄ0^I00b/@S /G/k;ү/ Į.c/".</a0U0d30w^.k8֯26 r0.֧LN/f0!-$\/AF/T,h>VͯS3L[QA'P 0Gӯg~9=˯}r."s/T/.AKt0=W 0 %/_q 00/0ipq/`1W0y 0{/t.$Ɂ0Nyگ/ 0m/CMG|40Gf.Q:-c/kܗ0/eZa̤/T/.5/0aޮ@/Ax/l.+Ƣ!b`M/3!`/`Ҝ/VWoq̘/mή1Ӯ/U"/@#-.Zh/௮0!t /8݇0ze.C.-ȯԮ A/a/QA.//Gf_g⯢ۯ_0G* 80Dׯ]aD0C nx//ު /..g/ބB5020ga/7j} */j"//EtLF P/{0QA.x /(v5/u0k;R0e*Og|a JW©/AXfJv0CwsJ/{^lQ/֧-%W/C.KȯJ:`eymZ0njXBWbSlGtbP07qNj;.˯o&O.î %үE0dWR/Վ)0Mi0001ST-0hVϳ0E"0Q/.+/fL/ٙ.֧/Tm0n0E/a^.lco/3H//گo0}[8X^.g//Fq2#\J#ݯ-/$\طӯUvJSlٙl/V>bg<4Z~&0/ίJU/:`eˊ/R:0-ÉUٙ/sOH\c//-/h80MˮO}0f0~.gEj02,0S3.%/6*/ .\&/*G(X.dۯׅS3L40ˑ="/0 (0/:`e.U8-P/S֯ 40# )0?/ PY}{7.\J#]//ؿ//v+C20X\J#0E/mp0B04/Р|/ٙ*/=/U^ӯaG1 %U.HCLn)/oGf.|'/*0?YSկ<1ުnn/GfLN/נF{0 Fk(,O/ /+@/+ `\K="/l3/ ./c?HQC/l3O{80/$.6T00X/FJ."&t0W0hw/$ /~0V$/-.;00V \C}.0_/'̃=0[Q /)fIc-.{^l՚07/{;p[0hwUB炰6>0iA0vT0w40M0[ׅh/Ӯ6J 0A//0J0/",d0 0˗00.(Ny;/90,l>/1.2 %Ү*;s0)/G0F0<02]/D'00H*/ٰo .Hܮ"ͯ8/*.r05nju\!k`̯G!e//S3̭ K2/P 4p/NVLC\J/$*/F0l?0/U0*$/c/D?ͮb#-݋F=̼0/s$\/ Ge/1/2\0sO/)0IG00m̘-nY<0;Z0K6`i:gR:0/qүeίt/DpX]uM-<﩯lp\:`eQNfS2../%"M0]E\C?)/4/B~/ /O'0W[//ޥ0H 0/qU].a.( /.D'k oc%/0_/:~&/JN0z /G//?!.s106ί/0?05K.00D/D'/fS/MF{0[c/C$9EԮm `/=$bU{ߨT0o0˅M)0t}LفHF.+q/8uR/km80/L0ɍU(+880D NvB0ȝ/گ`9\ p悳/'ic+/NA%(y/?U)ڞG8l3#]/yl4-LNq/6-K'~[I7-`M0S|/k -/jB6Eï,l/?IC/^*09/(v.)./Z' /9vr/tu}0۵ /NPLc+0IX/ꪢʐ N/BP0sTai.w@XkǯH{-Z0$/JUϧ0q/0 )1P-ODȰ/E.|'/j+0hOXޝ/wq@07/׾/./9,.w.nSK/AF/G80׾K' ?/\|0]c?eQ̼ +a-əծ:b|.cW-3]?QA0w/ׅhyl.]<[0400QA %U/\/+戏O'/%/.ˑ/ 0.Q0/ڭ!0FU/ϧ/;01A/JU/HCL0]40v¯0x-Rh}[80e.㭎wn.r/6>0P/ ,nuDa0r/ 1/yI0Ug0.0Ϊ/{U/~/]<[a0U<4tMTeZ/>(hO-P/87j;17/t.l0CI0Y90 ./0!|.#.۳0ۯU0$+0/y?8/d(+ 0l {Њ/D/pd00*vl3QAUga.z0FnbN0v0łx.V0'G \zr4dѰ0~c:aG8{4d/T,h/}0-/H//0ρ]0lM0XSO-_10M$*$//0 /~0 0_0//~ү߶/..6;/_/v|@|2 0`0f짯#1EjX:gI-1S/K0.n0q00ɰS0k &W,.=.Fy/f'_$ /(?2dQ6r..l.B0O䡯ᅰ(vE$0]:gI,*oطS09n-.8/ 0Fʯ֧:`V0\s/*/:`寒?/S3LO/{01//k .0 D<.l/-0S0\Jˑ/.|YE0#TJ04/<)O.X.G6-/r𪰥~K/Cw/p/y*(,;/2k /V0600ìXد)/h$//0.|ׯ+/ /./;/vB/o&!߬:b+/H\/N0@SA:.QA|B//wA-/_."Q0wS3L/ 0>/6W0]0^/$0g/W/T?.q0_04$\/30Dic<֓02ŮqٯL.87<0l3*/8//=/U"0fSXE (/W8u-Yo-6݋n!/^/X0֗k .-..M=;K/X6rPѯbV01= 0<)/4֓0\|Z0G8/0)..a0^5.;00qN.uC/.ϯm߮0QAO|zߣ#0lD9p0Jկ WĢ/{^/ZLfLί /@JG+g0Eު/$\.W[/'C{..a+_;2/}L.k l3C A5#0v/MK0f0=/ 0Eے.cp_S/S0c0Ӻ0D8 ,, 0[ 4M/Q.3{y/'Gcv .Fm/ү$_. .'}km/ ūA/J0墰//Jh)>+G+o60%\ZЯ*(yNNygrl=E&FX/򛮔\. . /l-v ?Q9)/~\- -".w/]u*08u-훶/G/mįC0*.[x^0.w/J\(4/r3/4/@0$0#1"0]u/$~b/\0Dځ[1_/ޯh.-g.o/.nX:0l?+-k/(\ /8u-|1/oڂ40.l3/t Te:e/O@@Y/Z20/eŒOZH<=/;.ab⯠.Xv/<h$/ު.x?#F밾I*/V 0(0#0-.:6>/ C$ 0/z0ze/fc/ǭ/Dм.v 0)/łKG.EC0߬zE0 /cW..֧\G61/H\/M/]e0G.n0S䯝z0a,0-/90bR/9׏Vw^>֯خ~I5g'GcР|:fTÉ#L̮Zh^ތ0Ơ!D0У0w0EԮ/z.0.Q.X0.Gʮȯg /{40F0:`e0Gh90xx.좚0\.̨S/,5rG/87/tl03T0YV/90K/+C0u0 Zz.'G..JM0fK/冷 /eȮ݋,e 2Z.3헯XlC񯞛tA0/G-5/ͅ0/(0;&2!/ ±%?!.&E.oc%1/n/ eY0/a7 /S/#0K0|0+0\09n0g0uDay='}a2Cm/M0p-qN @wޯwA-É.HQ0̮BG&NG//08700/,Eے/sO(L\s/p\Ac0.o/鬲/9/A/%U/)/&JgH\ٙ..m.@.6%0$\0 %0_TA~A^//!0#0P"0Y&[80/G.xs'"/!/3#00ۥDz0!X01/l@ł/-ʇݮ/_.]/x+0M/0Ƌ/xw0j"/*;XM(vM.kG/|(IZX T 5 p``@mѓa/0|.BP:`e.AƯw7P4毑8LN /=.Z̮_@ &450 /3'0ط/tO/nj,d0C`/WZ/AR0ZH8.*X/ުI/$گٱ۰f'x (@rҭ0Di/>D0%03ﯟ87/A. /0/ŞQg~9/'t. m 0M'20r3&/a2/+. /S0篞,n/ٹr.0ZzQk0 O䡯$"hB/.5G8/Z/QE0{/X //k=*.&/}[/V$.$#/ V0k/̘//נ/01S^/j-"~0Fm$0&NG.!f5/Pv?ng/S0-HU.Р/+/=20`>ԯJ#Y5!/'0>.rxC0//(ES0f/c[o&.36i#.B/ł/鯶 I/K&Q/ <'p-8sO.&̼ .oˊi0 /t 5Of60q&0LV/Cy0Col0//?M/Ϛ-֓0/8A090ln)/]T/;0y/ͯH_\ˆGV.F/T?a8oe0'0$0v/ ./V/k tTk  ZH,b[ Я"hwUخ/3Hx>?^k &NGDp/t:0H1f:gɬm8a/{S3L/0E./.ˑ.0`f/w.~10k/uV/Ʈ/_T͉/I0DqD0R:0/ZH/j\0 0 ɯ\Z0hB=0T0`/zeP/ڲG0ٯFL0_ـ/^0Y.8u/S3.K0  /0/J0 20(ܦ/Xł.a+_$#@,.l/b/x:ɯN0t|/-ȯ߶.(>/ίԭ@/eĥ54d0e*0|({a/DpXְIY/|f0Ej/|ɦ- 0Xl/Cw>(.)K0+ ;定SK'/"E;90`ͯWZk0fLή$*$%./lqìˊnZ/Sd}/v-h/&0#03//) /://= (//,ؘ.cb/n_0$0m_u /*/}/ىxs01ӯP00./t.F4/)0w.u=0Z. I}"i0!-l+47 W-qRʆq2,/="j;.Α/5.AI:b0E.-ڮ90///6ů?'K-T,h..a^/)7 ./V0̃/N}MR0/(0dۯ<-a/:lK^0B.Q0F0/t亯mέ20=/*0 .s/ 0 / /,,//0vm.ˮT-[įC/mů+0 0ijn/a/u.D-+q/ew"020+QA/ F) 0/՚޾"/G/ɯK0/?.C.E(*Q9Ưr򂮩n/0[.)q.A{^l"~4/9n.j {`//K/6/m80@S/D,_..~R/q//5/t/? P/-y*n,wt0R:0.*v/b/ .\C?D,ЯmMs1i[ԯ[Q/ˑ0\.|&ł$0CF0r/м/MO{ J#ٯު .a/x.r/į6.*// F.ϧ/>(ۭ;0vvL0``/2ݯ$\ X/Xu/E. 0m.㮡pD:`寊/X0ٮgE.U//yگP05 0.%M%/@S/mʰ7/R0R[0L0Wx 0Ŵ0k P.EC[Q5g. EcW/s-':gI.՚'/2CTe7x:Igïxz^/W!d0DZa/Tm/a/:(+oκ/ZH̘b/51mѓƯ\s.t__p0-,8? 6/-Nyg ~ѯ8>/- 08/l_q///hG/y<:`/z/u&07kU6<0ى%)fS/HCK/^?S3L0.Zĭ8aկPݽ/ +0//zf0I/0,Ԯ*nj/Lg0'./$.a/k/.NJ/uMU05/-#00݋4d/eZEے/Α.ϧ)Ű mX/Zz/X.-\㘯/6Wl,Pm/+0 \sfL/z/?/?4/ Ư7}://̃=/z./870t//ҵ.c?0Lk .̼/q,gE.J<06ׅ/1ӮR:0ǭ2,{;D~/qi/>O/ M/ˑ/(X0_3 -;1U/K/V0*/  j\fLN/_l0=-.ٙq/)$V10/>./uBk  5ҵ/ZL/ł/._PdE_.U4(@J.G8/rfS20wn/U0Q 0xs ,6//Z/hʯU/{Va="-Ģ+sr(0 0u&s/X.&/ݜ$֓)F/Sfl3!/n>a-R0[Q0[]/IN0S3LAf0J\6<*oުN./V/ m 0eZ'/:0Z/:9/C/l?̃=/ FtkA/ Į.c;0;˟/;˟/֧\C?W/ /=0X$(0`0"0n9n.:/ 0zůeX0ҭ0K0("ު/5E/C ;گ+/@ʯ=]1/Jڲǯ{$/7s9t /e0ޫ/JO/yl4 V`Ya/ 0e!G{;a0uu/.╱/sJ0K' 0.33/:&.(:`X.7/n.YtH*{iI*=Mߣ/sOr/l/sR)0c//W-,U^nF0_PK%11X8+w0 PF0݋.c&d/x 0adH1!0A0γ0'/(:gIqzG\JT,h0/΀0=" 0jB֧-=_'T/o/5"/Sl*K' 0Z?/0"ω/ͥ0zt{0/r:?XNQA+0s0x0e!G/)95ޯ"/<)-J\(R/+t0\\jR:.8շ/B/bfl(0|"~10ު/I30qG0/ 0$\`i/.0/_.^ T?0.16/#60R:0:gI-Ů8.70ޯ`0C>Fl80D0GN0.a/Ӯ:gI->. jq?+?Cq0m.xs~/ۼ/k ,0wS/ɞ@ʯ((W*[Q0*vF/D*ZH9/ 90X%w.>X0u/&NG.H،&0JX@1'TƠ)06-f0"'jk0XyBU1s랯9xw0e0I-ޯ0J/ܯw/IQA0C7/20Hܯai0$*lm= It亯)D/SdX)]{0߯w^9H0>EԮt|A-H-H0sJ-/1S/0;/Y0}5.6/k%\OZz/|9n-.r/ˑkv0 DO:0\stS\Pb0w0Q/ovH/{;/0Q?<0׾X-/"'0tk.̏/HW` . Ax//A[-@\U._gb$p|z0jt Iu00fS20*//L %0>Ԯym +/"M/ODH`/#.OL"ωX/Ӯ+0/`.v/l3'b//lm=暯D/4-C0/ دj_ـ0ԭ5+/`/c/p40r/,/$0h/A0賖}"/|/6h)0o`K///'2/PީC'ĭ"CI1l,M8F$ .c>/IX(茰hw/4Zu;'.yJiˆ/E/50-//Lg0dO:`S3̭oc00/1oc/ZG߰~+.㒰N]T,h/}/쟯 .v(PZH`0R 0ã]h/ì!ͱ/m/R 0/m0Ƣ0v­x,1P.N0tW0(@.`9'<.(/r/ׅhG8;00a0/eOS=0>/$po*֯ 0o430HC0/ 0Ku\J02/nj0s0Gq0 >0..V:gɭ3Ȯ/P=0Y/Te/$#@Pm/a%0nj VѮ Q/,,.yc+XT/PYt fr3.e09Y0/="/AƮ="5.O/OsR)ϰG/_km/:g.)/#1/,pt_87/<'-"<;01Y.06/U^S.:`a˯;̯!|b/A|) .a.ٯ4.PF $*$/̃/[Q0.^/:0/8u1Z0>/w /G"0.5 ~//C2/yG0)/"G8m.1S.S1 j!04/|&ׅh+z/w=Xa'נ.//0Z.5$A 0>`J0ׇ/\C^0B0)0;Fm$]1Sݟs?!./ %R/e/xo/iy/ipq/s0Z0~ѰwޯCDi/G8Cx([0i. /q7s90C0_/5zeP.X7.0mx/ׅh0 I/R:0/.0&NG/.DK DC, ] YCq7C/M/wv0֧' np^u;ޮS(05c0=R /r{^lg~X/'(Ŵ. 0 D/:g,蜮A/eV)/7/B~}-0G8/5-wSJUҦ#Tߣ3!ͱ/Sl zePZh/0=U*//0+q.R:-i/c/ 0>5[0S3L_l+@J-U";f0/0Y&06.=ؐԬc׮?!ZLJh0../eZ/uM/=&:0/OM/_hJYy"g0ߣ#0\J#,_֧-/EfѰP=|¯_/8u.=&0|/ 0-J/D.<)//گ+/ /gEj/0ïC.8[Q [[/FJ/s//7 WZȮ&0<Ļ/' Я/-{Њˑxs@=,,<Ļ(//)ría^>(-/xs@/ 毓j"%ۯV/p0<1+/A;Eےuï`/K/0$02/AL/0/ߣ.g/2,/ ƭ?/ /0HCҦ/J0?M0}/΂0Ϊ/5/?!/X.0Bگ~&/ 4M>6/3k o/05/n/e0/./.[ί!6X6l,4d/lj;/֧Se.l/x. /.ł/(/^Z8u60GJ_/ 0u/Y/an`r0;08u.j\݋0]^*V(0tk5/ׇ׾v."֌L0Z/!*.aze/:/0\C?DhB(/5.0 \|[Qߣ#/ .\C_0&/4d// .EԮ.7p0.᯻\s[Q04>(0\ZzG0Di/sc, ZP/+\J#戏0F0ˑ/+/נeZ/!b/,.0:`/)K08.՚ï=/<0ط/t'0U1C0r.֧q`M.A/l3.n.Q/'/r //,*/=&d 5E.YG/ %o&/{Њ/L/@z/nة|&91Α/D/Sdk]0!`/2"70x/r/t|O@/B~ zeЯf0D N/./O0p0l3|@0^Q.v=Ůxs.Fބp0K@60Q0:-r//8P/nj.)䈯rQ/_/iI0c50Eے /b0Z访$/mb /8002]/Ư^/T,h-ڻZ- i`/9.z09.-?!/3D"~>(8iC/agEꯛo_-///}0t3/-e//qU]P.Cw,/ϧ`/{.Xܯ%U+:gI.,O00{6.J/mV4.\|.g0+/(v.0fJv/N./,ܮ FS<^=ï6S0ؐ(vEԮ.-j.N'/"0̃=..n¯,/0p0ߣ0W/= /0BZ0\0L//<*$0sC njIc /< 0{7 0.d2%,!/ /3 @//cc o/#W)G-qS3̭8u- ֧.n-zeP|Y/ ,,.b;/,0:01l0:gI,,q*T/1)0z.E/1/q//ѯPٯ݋S|ZO0Nak+oc.!0/0nj /(/E/d(/K^ 60k .e0݋?/٬0/ X0.5M0\JzU/E0p/.X>T//xث+40ˑ/Y0 %0+AȶJծA.;/a7/Dit-߬LQ}+%MA͵/aޯԯw/] {=".|0*ݤ/֧@Αq/(vDpدy5#1O!%U+偯EےW/c,10+S0֯Vd0!b/ 0Rډ0m800戏/ 0*tBܓ0N0eZ/r߯j_wJS%D Ǟ ΑH1!/Zh/g0430 0gJծ:gɭު.D/_./N녯O~I/8\F0м.zE"'~T/fS2/uM0 ֧݋' /2/00W֯n,*)K2/Iǯ\\rt亯8u/ ./>/(/|)M//o0U./w02ܯ.fLί 0J0=l/n|ʒ/0/60nj/Uvo0y(O!2NK,%.)0L}#կ/Y&î4/n1/݋ .:`<;]<[//U,a^+J.C/]/Th/]<[.4}/&20//gR:D'00 0€/_0/2hB/Ny_.nj/U~&/%8u;˟,q.S-߯P׾/=~/qF0rACS<ǙůaE0P// .@S0J/彮gs 20fDitK/;˟.S.;0ЯT4 F. \IQA=".z0yïRb#^(0݋-z.O@ү:`/95ޮ0@z/o*V0/njCq.fni0uj0TrAf 0Ax/!ˑM0\ɯPY$*.௯ .aC eZ݋ᗳ:P.(Sl*j`/ e0, t*o)0J;0 (@/k0"07 WA媯6>-|ɦ/i/0`/Sҝm1V0-V$6m8/L#0-/;s0#/xr,&2x ̼.O@Y.0!1h/y5ipҵ.`#ׯqU.ze.eUӯLQ|')k?!.//0/-'-j;.^mڰ|j۫/8//m0ְd 0Q/î'Gc.As/`0/S0_(0vzeP{ %/./%/0x/:'0[.0d0( 0430~1-/.0O/o/|B/5.b"d)QA5O0/*. D/eʯG8|s=į~)/ 0J/30 lٯQ0Q .\s0.ڂ/[/.x/qN/l֧+/0S}^/l3/Mr0IcIV$( Q$֔B0+/@S=/&N. Cw./Z.oc%AF0J0{-a˸_1Hܮ/:`:`eJ0/R:0/t.RiW?M:CVɍ/;0{;/ l/tkd/XT;0IR:,Lg.A.@C U<>(VWo/q,~/j.)0bvD/` 0l3%SS0K0 /jřmѭZq3/Z0A/ad.0lJE0 iIQXSC/o86> )0ﮣ$0./d50ݯ 򊰈f㖏/p/'}/e/X.G/)ߣ#l00rh/Kw0ήį.80 .;/0.//S//1Sc~ @JB^0}/k .cp0B>&N/cWE.0{/bg//s/B/l3i3P/|.z0.㮐E0d0²0KN0F( F0!b//y0k 0 .DpXPo/!b.ܯwS'm')1I*={ Nyg-]O䡯 {/)0,-: /) :ljK/cүk /=.(v.a0EԮ.N/ P/>(f0.l0Q//$k /#/0/<)<)0Ny. .k /د'..xs0ڂ/+/?.q/:`/S3L&ڮR/pzGismZ識}//^ .\s/5xE{/ ,/D1lu0-//u0g~9s1Kt&20/.(-6+ՎH0 -?^qNy0 :AFEԮ-%.d/r00?4)/J7`:0ү%U.\.cwޮY0O//j< 0-Z0^0P=/c//sOhB0wᆯc/<0X/'w*| /͵.:8<¯``~LWrY /CvD06qa0ZTF/CwOi:g//=;R Ql.IjO0~0Cq֧sb0:gI,]uR:"'/k /ǔ/!6Si\-O//K0.瓯V00, / ^0kG/_Z.W)+/R/Vd0I0!/E/&/l/P-,dy3/AFC{w/ǯ뷯>Txs.Ӯ A.د՚ˊ!|&.;˟g0Q0R:0/n//d40ɖ/L//C).00|'p/l?0(@0:0ḯT40oc%/5.Яy>0+/ 0c?/X,g/hB9nqNyk;R.0f/}/13/H*.e/J#Y>y/Z-V4j.g}ͯLNӮ/.-:K0E/O/+- W."]<[J\C?a2/׹._t+m^0o %/!.U0~&X20)䈯QA-.hE3~Sn& 0 D 01/a3/00x:ɯf0]<[d(+ҙ/T6.t:0t/$90& =֧|Y`˴S<0쟮="V.eط/u}ͯ/3UѰJ\//t0€/&TvB/DitA媰X20/BvPl t/< m/|Y䯋|N} (į;G0"赯.]E.0Eï|z/ś/ [T.Ӏ08q0Cj9/".^nƯT/1S/:b/-/!/?!/ 0:gI.S3.8u./a,/^/9n-k k /LN`6J /h0/sO,xnj0L0ѯNy|)M0uV/5.C o. /0>(0G.X'.a/$\.#-Ȯ/Kw0zeP/_/#/kD-sJb#:/C 0Q///H+ e/zW+./xs..(0X/دZ./a/>(06>,A/7ɯR[R:"x/]*/*v0v /nr/$/l/0`/-TeuîI/@0m/ho*V/R:ҵ_G83{Q/ì/:yl (.Я//˸\0֓/s0sOb-70&0d[Sd,. Ʈ'}/j߮k -'.a/Ǜ0,0B/of0oc%\|J/j;.m/p#CM˯.k ˑ/!b./A/C 0߭xsy/4//0 A/L/ %(v5݋.)r/LW 0ӟ 0.h/p\A/402,:4*.ڻ/|rˊ!N0T7/6., 0/e0>0sR)006s֓v .4/Z񯫙/Oү<00``/l?~&0tL瓯ӭ,2\ pA0^ר/$\/T/ĥǭ/l/vv Ny/ҵ/0FE /Pٯ+/\ PY[/ԮPB4:Anj/b/ބ/K0>T0B0=;{^쮦Q9 i08X%ҝHw(@TT/50~R0E/.!0EȔ90ׅ.\s)0t//?80>T!|/1:gIPY/֧.lg Iu0k G8/K%/%/r%O@-h/Ư<;//8u,._-sO/{Њ.:`宗` {^M/|bJUJ.M00LN9n.gN&0ĥ5xz/ͰQ0m0.,/87acp.%U+ȯ3ȮO0 w/&x/-/"|/Ei/::`寨|,ل/z.A//QүL/G-q0Af/e.2$/Q./-?0;0'0O/ Fft:_ـ/=-w$0/#/,q/.tkҝȯI0*0yl4<+/!b-(D/h8'EHC-3,l30JUTT;믪/]|/A-A.4/z0 (_8<®!y/{;0 7&0CEtKK/.u0/P ?0~.5/__<;0Iٯ et ..nj %Α/?!.7.:`./Q 0 ,60 0e!/{//饯{ ū&NǮ뷭?/)'0ì.]D/ߣr0Ѯ?!)g{/%B07C/!100 +: { 0Ơ)0M%00//FJ0l//A0A/MR0_/\90:g-6k/1S6/*U0zn 0d06֓0/50,0hwկRa:b/(v!.h0`ͮw//nj/3:|((F ///CI0z/﩮DM05._.;҃p#r笯4//H\/j;0%U/c/H*]0wns/T/ S0 /-0"~ad.&NG/:` l/ bwHo-Ȯ7C&R v®C .̏y/ˆk ~`. /1Pr+d/Sl0+?m/B0nt B0(v-./0]0F|ɦ.Zr/n1njCq.m.u&/e/jT0d(X.F0?/Q/.1/]7.tR:0/V$0:/9n./8.]u*0 .fJ/_gb/ 0)K0//yCD~0a.݋:0/DpXAFR |bW)ZO0.Ӱ87.jԯM.;0.~&/|¯$*/e!Gj// ί/0J/~&06:`򼥮:?\/%)_D/"/_1.d[0 09n-O/W0a,lc0.l0o/_<nj.[x/30Sjïkm呰AlfAx/J/#B~ 0Ic <).r.9.QAzǯR 04ff0ˑ0zӆ|b0ʿ@>(/|i0 0sگq7/:gIAx/T,h.S/oc%9n.Af0Yp\⇯bl+0/V/8u/(v/ e0DSIGq͵(0 //R/)00%0֓0nj-֓/Ax/ /0!D_/{ 0ˑz08/l3Cw-ȯ/1Pr,-6>/hy*"0hi[6J /6+E(/ e0<0U0g0-a/="-2])9ˣ0{i0Pݽ/X/ߣh//D-ZAl3+y_/ڄ0D/|/,,j;3HLg0?at(/l+Q/V / .0ï$/Eے.mr1S/C0 .a^/<)/:A%HT^5w0%U+/eZ//Ԯм .l3.0ĥ/S3-$ѯ"/:gɮn߯<)0L/="$\(-3ȯ(v/Zz/->sL/_/u!0w//Eے//i@0.D.@J/`<0?x_/l m80?!/Ny:`e//&209n--l 0vvL0Z/06C. 0O@0S3̯~="/6ˑ0TK/_ -, $0:/Z.Q9fS2(ݯG毺cW/R:/.[Q0S0دݯT,/>Dnj. 0./>B0&䯇. D0T,/2,0 /6>/k .uu0k x/I/n/+0֓0]0.a鯞(v0lA03q火0R:0h0+-0{/!C݋/D.EԮ/?!.m/a/D.e0Y0./.9n//\s 0./:gI0]0/CX0C龯ބ0(vmNj;*/l3.`/D<0/Z -/֧?ͯ.L/ߣ_.D+k /S00X0E.0W֯/0$ //m./S3L1Sp0l37fLΰ/:gI/zeP/՚0(/xk k /l8:`e/S3LC'̃=0_1/{  Ưٙ//..6ߣ#0C/ p/-@/:g.xs{^l0\s6.k (/߯/!bǔ0=":gɭ:`R:00D_߮D߯nj/0:gɯk [Q(va//9n-/:gI %0k l.k 0QD/_/_?q/mNo/x:`e:gɮ0֧:g.ԯQ:g.D{0l3-_/(v/T0`M/6>//Z/'0֧/ ="'lD.:g.8C0 (/߭ҵ/l3 F0T_9n-D6/֧D.D/6>0/ߣO'0:`/6>0߮߯l36/D/9n-_0D0 (,rE.A0.D:`e0D//l/(v0l(v0D/00q04/C00(/l3k l/l.l/(vl.l3l.nl0D1=0:`e1m09n0l3D12Dl30:g0D_D1l3Dl0ll318ul0l30ll30l3lDD10lll3/_0l060':gɰl3/l3DD0l30߰l0l30l/l3D1D00n0l0߯D0l0l30l3l/ll0_,,ll/l30Dl1l31DD18l30l0l30l0l3l31Dl31l:gI(l/lll30l:gIҵ(԰l3:gI18uD l3000(vl30l3DD1l0:gɰll30C0l.l.l_0D0l3D0(v0D/_0l3l30(vl/l/߯l0D0l30֧/m0l_0DD0l30l30԰l31l3l30"'0"~l3l3ll3l30l3D0D:gID06>Dl/Dll/'0_0D0l3l30lD0DDl.DD/D1l30'0l/6>0l/nj0:gI0:gIl_/l(0l30D0l.l3l./0l3:g.l3/֧l/l3l3/8ul3/DD/l3߯?0l30D0߯0(D/߯Dl3D__lll_llT(ll/;҃l/q00l30D0:gI(v/l0D1l/D1l0ll3l3l308ll/:g/!0l3n/l/l3ll/ll30D0l30l6l3ll/D0֧0/l308uD0l3/l/l30ll3ll3Dll3l0l/l31l300l30l3:gI lD0D/l3_0l0D0D0Dl3l/0_0l0:gɯD0ll0_0:gɰl/ll3l3D0l/l30l3_0D0l 0:g0DD0:`/_/l3l3Dl3/l._0Tl3D/08u0l3.'l/֧l/8u0:gI0D0D/6Dl3D0l3__/֧l/l/'0l.lD0ll30l.l/(v0(v0D0l39n-0:gɰl3l.l/nj0l.(/l30l3D0l30D0D0l/l0l30DDl3l3l3/D0ll0l/߯݋l3D1l/l3/l3lD0l3l31l30l30ll3llD0_ll/Dl30l3l3/l30k :gI0߰l/l/DDll3/l30l30DÉl3/_18u0l/ll30֧l31D0Dl30l30ll30DlDD0l30l0l30l/֧0l30l0D0Dl_0DD0:gI0(vl3:gɮl30l30D l3./l.8u0/ll/l3߮lp/QA_/D0m0l0l3D0l.0l30lylDl3D0Dl3/llD_0(v_8ull.:gI9n-_0l3l/l3/l3l.l3/l/߯߯l3l3_0D0Dl/:g0l֧D0l3l/l.Dl3l3/l30l3/_//:gI0݋DDl3="0D0nj0l0//DDl3.D,_l3_0l3:g0l/D/n0l30D0_008u/Dl3l3l/llll3l3_/l_0l3/D0l3l/l.D0D/l/'0:gɮl/(8u0l3֧/l0D0ll.lD//l3.l3mlll/Dl/l0l/֧/D0l30ll3/:gI0Dl30l3=8u0Dl3l_/D0_lDl3/l3/l3mNl(v0l3/l3l3/l3Dl3(l3/l3//Dl3/l30l3k ll30D._0l3/_0D0lDl߯Dll.D0l3/_Dl3l3/D0QA0l3/:gI1lDD0:gI06/:gI0l30l3k 0/l3Dll3 0'l.l3ll3l3/l/:gIl30D0Dl3DQA0l3/ 6>0֧l3l3/_DD 0l3/D0l0/l3Dl3l.n/l3l/l.Dl_ll3l3/l30l/:gIl/DDl/:gI6/l.Dl3l,D0ll3/0l3/6>0/0Dlll/8u0mN="0DDll3//'//:gɰl3l/l/:gI:gIl3/l3l3k /Dl3l/El3D1l/D/0l3l3l3l30Dl3lD0lDl3Dll3/nj/l3l.'/l/ll3lC0l3Dl3l/l3/_00Dl/l3lD0l30ԯnj0D0D08u0߯D:gɯD:g/l3.l3/l30ll30_l3D/8ullD.ll3.l3ll3D0D0l:gɰl_l3/l3/'0l0nj0l/D0Dl0D0D0lA0D:gInj1߯0l/njl3ll3l3lD0l/l3/ԯ:gI:gIl.l/l3/Dl3ll3lDl3D0lDDD0ll/lll30߯l3߯l/D0D0l.D0'0DD/l.Dl3:g0l30ll38ullD/:gI/l30Dl3l3/l30T_0/l3l/l3/߯l3/l/l(vDll/l30l3mN߯:gI0D0ll/6>l.l.llDD(v0l/D_l0_Dll߯l38ul3/l0D1l3l30D08u/Z0_0֧l:gID/C0l0l3/ïp0Dl0D0Dl.l3//_0:gI0lD/:gɯl30D0l/l/D/(v0D0D_0D/_ll(v/8u//l/D0l/l/ll0l3/߯_._0ll3/ED0l3/'lTDD0l/lll30ll3/8u0mίl3/Dl3l:gI/l3D߮l/l/l/D0ll3߮(/_0DL//_8u0Dl/l/l39n/l/D/l.l3/l-_l3/:g/l3D0l:gɯ:gI0D/l߯0Dުll3D_ lDDDl3__/ll3lDl3_l 0:g0mN(D(/1S0:gɯ:gɰl30l/l/Dl30D0l3D0l3:g/l3l30l3/l3D0l/lD0Dl30D0߯D0l(v/Dl3/l_0l.l3/:g0l3/DDDl3/D/:g/Dl3lll3l/߯0_0l3:gIԯDl.l3/l30l3/l3/ll.l3/l3/D0D8u0l/l/Dl3/Űl.l3l3D0:gI0D0D0D_Dl30l/lCl3/l0D_/lDD0D/Ԯ(/D0l3/D0l3/njl_'l/D0nj0RS3̰lDl.D/_/D/l8u8u0DD0l3/D0D/D/_Dl3/:`:gIS3L?/T/l3/Dԯl3_0l3/DDl3.8u0/8uT0D/_/:g0/l3._l/D߰l3/nj0T0l3'0D0(l/l3Dll30A0_0:g0(vD(/D0l/߯_l36>0Dgl30l/l30߰l3(v:gI0l3Dl3 0/l3l3D/8uDl3 F0D0Dl3/ٙ0l0lD08u0l߯_l3DDD._0l30ll/l30(v0R:00 0D0D.8u:g/m0l/l3/ll3l3l3l/D0l3llnD/l:g/_00l3l.DDl.l306>ll30D0D/DD0l3/D0D_l.l3.l30D0l30D0DD(l_0.l/R:/l/l3_/l.֧l.9n-0=/[Qk 0DDl3D/D0ll/ll'0l3l3/0߮="0lD0l3D0ll3(vlDl/ll3l/l.l3l3D/ll30cWD:gI0ll/(l3Dl3'0l.T0l0l3/="0:gIDD0D0_0/l3.DDl.DDl3D0(v0Dl3/l3D/8u0_DR:00nj:gɯ.l3lll0D/lDl3Dl3l3.ln/l3l3/D/(vl30l/k 0l30l39n_0lD060ll3/(0_DD0/l.l30(v0l/D/k 0l3l/D/:gIlx1Dl/_0_l3/l3/l l3D_0l3l.D0l3:g/#8l.D/l߯ll3l8ul.l:gIl3l/(v0Dl3l'l/l30Dl3/nj/l3_l/߯߯:gI0Dl3l3l/D.l_0T0l/l.nꯞl3l30D1l.l30ll3/l30ll30D/߯l30l3:g0Dll/=߯D_D/DD0D/D0l30D0l30DD_6>DDll/_8u0l/_0/D0/l3/llބDl/0ll30D0DD/DD0D0nj0:gɯD0ll3//D/'08ull30l30njD0_0(0l30Dl3_DDT,hll3/ll30ll/Dl3/l/l/l3/l/Dx(/Dl3l3l3_l3l3/l30m.lpl.l/(/l3/6>_֧l/l3:gɰl3l(l3l:`/C0l30 0l3lDl3/Dl30D:`e/l3/xD0l/l3/l3l3D0l3/l3l3l3/0_0l30k 0l/:gI0D0l(/l.ll=l3/ll_08u0Dl.+0l3D:gI/(vl3(v/pl3l.l/l.l/_0l3;0_0l3/0(v0/8u0l308u0D֧00_ll߯l30_06/l3D0l3_l/6>l.l(v/8u0l߰:gɯT0l3/6>0l.lD:g/_/D_(D0l/ll߯@J0l3l3Dl/l3/l/0Tl3/l3/D0l3l3l/l:gI/(/(v/0֧0D0_0n_0\0l3/0l/D008u0l3_/D/8u0_q/l3/D0:gI0ll30D8u0l./_0(vD0l3_6>ll.l3/l3_D֧{l3l3(v0l3(vl.lD8ul30߯/Zl3(v0l/l3//D0ˊ!0DD/0:gI0l30D0ll3/_/0l.l3D60l/݋'l3D:gI0ll300:gɯ_0_0l3D08uD/k /_l/l/ll3/l3l3/l..al30D0_l3lD0="l3Dl30l3D/DC 0D0l309n-l/l/D06>l30l3l30_/l/l//D/D/_/l20l/D0D0_0_߯D0l3l30D0/l3l3.D00_0:g/߯l/l3DD.D :gI0D.7 װ(:g0:gI0l3/nD/l__ll3Dl3l36_/l3l3/D0:gIlDl3DDl/="R:00:gI0_/l3Dl/_l/_0:gI0:gɯl3l3l\0DD/l/D.:`D0(v0l./_/ZD0D80DD0l3l.l3l3/l3'/:gI_0_ll3l8ul.q/l30l3l_/(vl.0l.D0l/l/l3//l.(v-Hl3/D0ll3l3l30(0_0ll3/ D/D0Dl3/(v6l/l30l3l3/Dl-8ull3/l3 /_0l3/_lD/l/l3Ԯl3_ll/D߯l30DD0l.D/:g/D0D8uD0_D0l3l(/l30\D0l30l3/l/Dl/l3l30l/0/߯l3/l30l.l3.߯x*ԯD/l3_0l-60k 0l_00/ll3Dl0lD/l3D/l30lllDD0l30Dl3/C 0ll3_l3/l3l/l/D/:gI0:gI/D/l0/l/l0lll3.D/0D/:gɯl30l.D0֧l3(v0Dl3l3l/l/l6/߯l3ll3l:g/_D߯6Dll30D/l8uk //0D0l/D/D:g/lD//l/_֧/l/DD/_ll30l3l3l-_/D00l3lD(v0_/l3.'\s0k 0:gI0'/l//Dp/:gɯuC05(/D/D//ll3l/lDD'k /l3l3/D06߯l3l3/l3l._0D((v0l30l3߯l-l3l/l30D/lll3֧0/Z/(vD/D/l_lDl3Dl3/lD/DlD݋D8u0ll3_0נ/nD/l:gI0 l3l3/D/D/l3l/D0ll3/D߯_/l3D/:gIall3.l//Dl//(v0l'>(Tnj/l3l(v:g/l6/D0k D/5E0֧0l30l/߯"/l3߯lD/l/D/l3/l3l_0 0D(0ll/Cl/6D/.l3l/(v/D0l.D:g/_l3_0l308ul3/l3k ll3/D6/:gID_0D0Dl30l3/l30D/q0֧0D:g.D0l/l.D/l3D0D0Dl//D0Dll3nj/D/D0l//:gɰD0:gID:gIl3l/l.8u0/D/C0D/l/:g//l/{߯l/QAlD/D/Dl3/="/6>D0_0l/_l3D0D %֧l3/l3/l3/l/0D0Dl30.ll3\s_0l3.Dl3.:gɯ:gIl/D0:gI0l/_Dll3.x6>0l3D0l/llD0zeP0lll3/l3l3/l_0l3:gɯ0ԯl30DD߯DD.l3_lD.//l30/l.l/l/l3D:gIl//lD/l/l3D/l3/j6/8ullD0l30l0D0(v/DD0_l38u_/D/n/l.l3/߯l=/0E.0l3/Dl3D0l3/D0(v/Dl3Dl:gɯD/l3/l/(v0x1l._l3/llDD0l/6>08u0l3-l.֧00Eے0D/l/0D/l/l3/l3D0QA:gI/_l3/D///_0l3ll߯D߯/l3/lll3l30lTll3/݋߯/m/DDl3/l_x_Dll3.l0l3D:gɯl3l3:gIl3/D00l3/="0_l/_0l3l300l3D/݋0_/:gI0*o0:gɯl3k ߰D00 F/l/l3Dl0l3.l30D/D/_./Z000l3D_.D00l.l/l/D//߯_0l߯l:gI0Eے0l30ll߮j6>0D/(/l\D/l3.lD0(/(.D0݋09n-0l3/j;8uD/Dll30l֧0߯l.l3/l3lcW߯߯mN/l3.lDD/l3DD0Dlll//߯l30/Dl3/_//l/D.ll3l3/D0l/m/_l3/k_(8u/(v0D/l/l3lDDl3l.l:`e0l/8u0l3߮l/n'D6>///nj.Dl:`e(v_0l/l3/l3/l3/l3.l/߯Dl8u0/'/:gI0l.'0l30l3/D0:gIl3/D:gIl3l.l30D0݋/l30D:`%U+D(l.Dl9n0֧0lDD0_/T0l30߯nj0l30D0l30Dl//k 0T'0l3/.l/l3/:gɯlD/D_0Dl3/D߯D0k 0l30l3l3mN/(v0l.l.TDnj߯:gI0߬(v/A_lTl/l.߯8u0nj:gɯ(/l/D0l30l3/D0D/m8:g.lD/9n-֧9n-0-.QA0nj0(.l3/߯l3D0:gɰ6/l3.l/l3l3/l3D'0_//00_0l/(/8uD8uD/԰Dl3.D:g/CD/l/ll/Dl30l3j;D/:g/60l3/0_00D/݋T,/l߮D0l3Dl3l_0l/D0߯l8u8D0D0n:gɯD/+l/D0l3(v/l.l//ll/߯l3/:gI0:gI08u0l3/ll3 %/A8unjD0p\_l/l3߯l30DK0DT/:gI0߯D/ll3/l/l30ll.(l3D0(6>߯__l30l3D0lnjQ0ll.l3/l.T:gI0_/8u':g/6>0:g/l3Dl3l//D0D0l/D/9n֧l30/:gI0l.l6>0D0 %0_0l3/:gI߯l3/l3֧l/ll3l3//_D0l30l3/:gI//گ(v0l3l֧0ԯQ(Dl3'֧/(0:gɮll3D0C0l30DEے6:`/l.D/:gI0/(v0l.=n.l30ll30DD/.:gI0l/Dl30ԯ8uDl3(vl/:gI0l/:gI/l.=lD_D/l/lD0D/.ll30߰06/(/l/.D0Dl3/l30D0D0mίl3l3'l/ll3(v0:g/l3/DDll30T0_0ll.'/lq/l///l8:gIl3l3/:gɮ8ul30l.l3.8u/Dll3:gID/8u/݋=/_0l3ԯD_/l3.l3l/D0//x0_(v0/l3/_/l3l3/n/l3l3l3l3/߯l30lDlll.D/l/l/D0(v0C0D0/l3l3l.xl38u/Z8u0/D/l.l0߯80߯߯cW="0ll3.:`/l3l/(v(v0l_/l3.ll.80l.0/:gIl3l3(l3l3D/(v/l3/:gɯ/5D//_l/l9n-l.l:gIl3l3 __/D/l3/llT/ 0D/l/l3/xll3D0l_/0lD0l_l3_/D/D(v/'Xl3/:gI=n//Dn/l3l3l3/.l/D/(vDD0l3/"/l30l/(Dl/D/l3/(D/l30l/l30D0/Dk :gIl3tl3_0606>l_/ll30l/(v/߮ԯ0D00l/D/l.l/l._/l3l.l3l3l.GfD/l3:gɯl3l.ll.ll3/D0߯8u֧D0l3/Dl.DD/D8u0l3l3/D0ll._l3DDl3߯0:gIA߮l3:g/lDl3D/k //l3.a/D.6>l(8u/u&l3./D./D6>0/T/cWDl3l/8u/l3DlD6l3l3l/8l39n԰8uD="0mN00:gI0֧/(/8u_l3=Dx1:g0'1lk 0:gI.Dl/8u/Dn0D0D0:gI(/10:`e0D/D8u?0m/({0="0/(/:`0l3//cW'D/ll3԰D߯__߯Dl/l/l38u/lïT_/D/8u0:gI0T0-w/ԯ߮l3l30/l3.0ҵ0ll3l.l3l0l3l3.l3:gɯl/l8ul-l/=0D0_0D0߯:gIl3l/l.0_08u00Dl3l:gɯ8u/l3D(/(vl3l3/Dk 0l/(/_߯DD/Dl38uT/߯8u/ߣ#l3.mίl3l30l3D߯:g/D/:g/8u/l3/Y&0:gI0/D/l.0l/l3/9n06/߯D/l30l30D6//l30lClD6lk :gI(v߯(l.lVl.D0D:gI/D.߯lDT_0Dl3/_DD/ll3l.l.l3lnj`ͯD.D08u߯߮ۯD/l30_//D.l9n//l30l3/0lD0:gI(D0/DԯDl30S3L0:g.l߯|ٯ߯8u/C/l3.lD00D0֧0ll.6>0֧/l/0:gIll_DDnj0l./l30l30lR:/Dl3Dll3''_Cl38ul30_/ll.暰݋l3/l3/D.0l30D0:gɯD0l9n0="/k ֧/߯p_/(/ѯ(v6 '0(vD/:gI0(/0D.:gIZ8u/mίD/:g0D_:gI/8u0D 0 {DD0qDlD6/D6>0l:gɯDDl3.(/D/8u0l3Dl3l/8u0nj0_A0߮:gI :g/l3/l3//.x(DDl3/l"~0l3l.lٙ(D/l3/D_/DnD/߯ll.( %0:gɯٙl300T,h0D/l.50l30l3.֧l/0l3/l3/Dl3lDD_'08u0l.l.l3l3/_9n8708u00l3./D0lk 0ѯD0ll.l3/D0D:g/ Fl30l30l_.~/l/8u0/D0_/mίl/l8u0߯l3_0l80֧__l3D0:gI00_0Dl/߯xsl(v߯l30D00lDl3ll1Ӱl.l3/:gɯ:`e0֧0T0lD/Eے9n-K/l3k -ll30l:gɯ l.(v._/!/_0DDl3/ZD/l'm/:g/(nj//Z6>Dl3_/(vD0(vl36>0.D8u.8u0k (/lmN_/k ߭:gI0D/Dl3l.:gɯD/9n/6>/C0=0֧/l3/o&l3/0/lcW0 /.݋(v0T00D/!b0(.l3/D_lD lDlDk :gɯ08u6l.Dl3/߯l3/l3/l3l3/:g/ll09n-ll/l//l//D/0D0l3/Tnj0lDDD/mNï(/.l3Dl3l3߯l3l/l3_/Dl/߯ 0/lD_:gIlDl3lD6D.l//lD//l0l.:gIl30l3/lD/l/֧/E._'0DDll3l30'0ҵ.l3.lDl30Dk 0nj0(D8u00߯0/6/l3:gI:gɯ:gɯl3'0(/:gɯ{lDl3/(v/8uD/D/߯(/xD߯l)(l8u08u/l3l.D0l30l3ԯ="nj//߯:g/D.l.DD/l3.Dll3.k D/߯߯}/nj0l38u0//:`/ll3/l3k sO}8u0D/9n-//D:gI]0DDDl3!///l3D/.l6aޮ0n/D/=/l.8u08u080l.(v0֧0_:gI0'0D8uD/S0/l3//({0:gI06>0'/0l3.J\/9n-R:0D/Z'/:gI/l6>ߣ/9n/Dll߯:gIl3/D0D:gɯl3ll.l3/DD/l3l3/נ/l3l3/DD//l/l/l3/80/l3/:g/l_0l3l-:gI0D/D/D/(v/_//(v0.l/D0l3/l3/l3__:gIDl.l3l/l3/0(߮D/l3߯DD/'l3/l.ll_0/0C0D0_0ïl3lD/_0'l3="0_9n//"~.lD/_/lT0p0DD/D0l3.8u06/08u0(8u_C08u/0l3/_/l3.__֧/:g/(/9nmί_.k q0֧D.a="c/l.0Tl-69nl.+ 0D0((v:gID0_ll3/D06.߯ԯ_m0l3/l/lD/l3߯l.5lD(v0(v0l0_l.:gɯ/6>_lnjDDD6>0_/'0D(v/l3l30/(6>/:gID(/Dl3lD-:gɯD0l.D:`/(vl3.l3.T0֧l-_0nj06>0DD/_cW'DDD0[08uD:g-l.:`/.l3./D6>0Dl.njl:`0߮l8u/D֧/l3l3_/l3l3//D.ԯ8u:gɯ݋߯:gɯD0:`e00D/D/:gI/6/./D0T0/:gI:gI0/l3//:gI="߯:gI506mί6>ԯ="6>l3.ll/l3l3]06>/'00ïk '//:g/ 0Dl.(v/D0l/D0l/6>:`/(v/D0/I*=0"0_0'nj/D.66l3/l3/݋0:gI0(/8u0D0D0D/0'/l30l3/_:g/k //߮'="/߯D/߯l36>l.l3l3(v0_l3/Dcׯl36>l3.l3./ (vDl.Dl3/lD0q'0/(v//6>0(v-_/l3Dl0l.0(vj;8u/l3D/_D:gI/ 0(/D0l3//0k (/C00tk0nj/(/D/(QjD0/Z0D.6>0_D:gI="0l3'00:gI0lDl3/m0:gɯl3.l/l.Dl3l.D'\njl3k T/nlDD0/(vDTl/l3'0 QA0.0(v0_/l30pF/D0q0l.nꯅٙ/?/0l3/:g//._="002l3.D.l3_ll3/_0k '0mN_:g-0l3/9nlD k {^D..D:g/:`_/l/80l3/(0ll.D/l3/0D.߯l3/CD݋_6>0:gɯ:`寮q߮ï:gI:gI/l3(///l3/_(/D.6>6>0mN0_/:gI/_-ԯ8u//D/_D!DD/_D/_0k /(D/_..Dl:gɯk l3.l3D0D0D/l3_/_0l/ԯDD/l..l3//0E00q0l.߯62,(v00l3//5/_l3l3lD/:gIl-D:0/G/l3k /nj0D/8u0l3/Dll:gI/8uk sϯ֧:18u0"~l08u(vv 8uD/l308u߮l3l.l_l.Dl3.l3.:gɯGfl/QA(v/l/(v0D//D'0l/'S3L0D./'0:gI0_0(/T/D08u/ԯl3/ l3l36>/lD/(v_ll3="0:gɯlDD.l/DD0l3lD0/="08u _/l3l38uD/D0l30:gɯl3l.'k D6nl3-֧/10ll. 0l3:g/{ _/q0C0/_D08u08u0DD/l3 0l3.0D0D/(/l3D0/:gI0:g/l.(/l/l/D0CCl3l36:gɯD/(vnD/(/l3߯D(:gɯ:`/:gI/:gɯD0/870:`e/D:g/`L0Dp/ F0.k 00x0:g/l:gɯl֧0T0/Z0߯l./l3.mN/:gɯ_D0Dq(-k 09n0l-֧/(vD/l3.6(/D1S0 0l309n-0l3/_Cl//D/D_.D/.nj/l3/گ[/Dl.D//گ/D/8u0:g0l3l/D:gɯD:gI/D/8u0D֧/8u/vHl-6>0:gI W=l3.l.k 0D/(vl.DD'6>0l֧/8uD/l3/8u0l3/0D/_0_/:gɯv //D/'/:g/k /Dl3(v/8u/ԯ/D_/<;ll.l3\8u/8ulD(v/D/'l3(l38u0(///ïl3/DD/'}l/6>0D/lDl3/DT8u0:g/D/l8DD.=/R:00/ F/_/6>0nn/(/Dzg(0:g/k l-(v:`察8lD.l3/l3/:`e08ul.8/ /nj0(v/D:gI(D߯6/_/(Dl/'0t|/l3.D/_lv x Fl_/9n/00l3/8u0D/Dl3/l֧/8u/ll3/l3.l3D/l3l3.o&ԯl3.(/lx0$ 0D/֧:`:gI/6>l/(/l3l3 % 0l.8u09n0D/0l-8u8u'D/6.'0D_/__'/lD(Dl3/_lD_l.(vlD0:gI05/l30D/֧/D/D.D0:gɯ(v/:gɯ߯:gI/l30D//="*_:gɯ6>/DD/lU0k /p/D/l.QA:g//_T0'0x.l_0nߣ#'_(vD8u8'0/l3l:`e njqqT0_ Ʈr0lm/ /.8u/ 0D0A0l.nj0D0D/l/0/Dll.n/:gI/:gIl3.8u6>/ 0Gf0D.Dx0l-CSqNl3.8u0l3/6>k 0oD/0/l.lD/Dl36>'0nj.6>C 0T0x0Z/0:g/l08u/:gI:gɯ(v/+06/l30/9n߯8u0_/:g/D:gɮl-0/D/6>0֧//6/:gI0mN0/D6>/:`e0Cl6>0CT,:gIl-8ll/k 0֧8_0:gI0l(v ίD.D/T_lD߯:gɯll/=k '0/l.l3l3D.l.l3.֧߯ 8u/l3mί6>0D00T0Dl3/:gI0l30l36_/6>D/(D֧:g. /C֧8u0'0:gI/D//sO:g.l.l380Dl-֧/):T06>eZD.D.(v/ߣl3/l3.݋0/8u'l.l3/l3.n8u/D(l/0߯DD0D/(vv/!b0CD/'C0l3/D'D/6l3/8uD/0D/EԮ06 0D-[0l3/k l3.nj0q/l.l3l30(/$0ު00njl+D/0Dl._ll3l(9n-_l߮, lD/l3/Dl.T8uD_/l-݋ll:gɯD//l.0ԯl.h0j/D/8u0l3/߯D="l3./(v/lD0l3T08u/*0C_l3/6>0=8u0:gɯ_/_/0 //ZTzeP0:gI/_ҵ. %08u/7.l3._/݋:`e֧/Cl3.ql3/ïl//D/l9n-0l?8u/:gI/:gI00_ll/k 0'0ll3ll3l/_/9n-ԯD/ 0T,h0l/l3k 0l/_.8u0l8l.l/TQA0_/__/mί0m0:`/:gI00Dl/,/򼥰/Z="(vl-߯D_'E.ԯ_(lnj6>T/l:gɯl/l__:gɯ '_֧߮D0l3D0DlD/lTll3֧l_.D/6>0mN00l.l30l3/0j/:`e0l30ai0/.c0݋8u0DD.l3.֧/l3lD/߮'0l/q0A/:g/l30DD08u_/E.06"~0n/Z_ l3l:g/DDl/֧0/֧5 %0DD/l.ll/_/l3mN/-/Zl:gI/l3-l3/߯_p:gIl3///T l3/D.'k D.Q8u0D0l.k /J.k 0lD/߯//l8u0/x0݋8u.:`e0T08uDl3/*ol3.l3l3/fS2_l._/l_/-\s0/_1c//:g/l3/DD:gI.l-D_/_0l.D/l3ll/l3./l-֧:gɯ'(vl3-9n/D_/l3'0(v/(v݋/8/=l36l.l3l.l3D/D/߯߯ F0:g/l3 /C0n/D/l3.8ul/8u:g/( Ư6>T/8u/9n/D.:gɯ8ul8u߯.֧l3./k _l3DD/Za֧/گ_.l/ 60:gɯ0D/:gI0l.D/:9n-(D/_/D/O@0_/l3.6>8/T,hmN/D-:gɯ:gɯo0\qz0/C06l30:`e0/ Ưٙ/:g/ll3/l3//(./ZH0l3.l./Z'Ct/(/:gIl_/Dl8u/l3.l6X0E0(/T0l3.֧'}/Z/֧ _/l(v/l3.l._ 07{k /ުl30l3/' 0mN0֧/0l3/_:gɯ_=/l3.="ˑ0lD/8u/S3L.l/l3//گD/T F{~//گDl3/8ul3/D/8u(v/?0݋0l D:gITnDlD0/l3`Ͱnj//Eے6>0_D8ul3/'(/D(vll3/C DD̃=08u/mί- 8u06>06>_09n-6_/D0&`M0֧0 Ư݋/߮ԯll3:g/ 08ul3l,x0(ԯqnꯞ/l_/D0l.nꯞ.:g/_/ll/:gI/l3DDD/9n/8ul3D/(v0TDl3.ll.n8unꯞ^nFlD0nj_(/8u0(v//:gɯl֧/l3/9n-0ΰA:gɮA0:g/-PY0֧//=._/l3./Z/_0:`e/߯T0  0:gɯ_/nD0DQ90/\/o&0֧(/l.(v/_0nj0߯(v(v/_k 0/l-D(v߮0l-:gɯ'/:gɯ_/D/l3nj 0:gIl3./x/k Dp(v+D/njX/./1S0/mN1n꯹j;1S0l3:`/08u0_l3R:00Alnj"8u/݋nj0xs0(/l0:gɮ.:`e/0Dl3k 0///Z0:gID/l-Clnj/m//Dnj0l30nj8u0l3C{0l/6T/D08u08u0֧R:0l3_/߯l3.l3.l30/D.'/(/_/l3//\s/߯:g/l3[Q0l.D:g0l3/0_/l3T0-H0l(vٙߣq0=l3Dl3:gɯl3D/x0m./9n-0:l/_/ /T0'k /֧/l3.(.o&l3D1l3.lD݋/xs/6//8u0D/8u//8umN6>/ݯl._D/T/ll3.Z'0(v/_/_/l3T6>_Dl3-:`(/*0DD0ԯ9nmN0:gI/Dl/0_߮X0_/k 0'l-l3D0C0D0:gɯl3.8u:gɯ/DDDl݋/hB0l.6(vD֧//߯8u/߯8u/C/l3߯6mNq/:`e8u/l3/86/m/_l0(v/߯/:`eze/6>/A0_.D0_D/D.:gIl3/Xl:gIl3/6l3:gI /*0 0qmίxs/(v//lD?/ %_(v'l3/:gɮ:g/֧/0D/6>(/'lmί86>0/D8u/c/.l3T:g/S06.(/u /Zl3_ZzmN0l.l3D_.p/qN_/l3.(.8ul3.l3/6="0QA/D.(Dl.k 6/-ȯl3/zeP@J8u(l3lD_/="0:gI0l9n/l/ /:g/D/((v/נl3_/:g/D._/D/l6/l3.yl400:gI_/0߯ll3nj/(v8u/mN0/l3D.9n/(/(߯8uk DDl3. %0_/D.D0_/֧9n-0_( *o (l3֧/l.ܮ֧Dca(._1D.]:`eDѰ6>_l8u0"0{0/(v/l-l.D/:gIn݋/l3-֧/_/_0S3/l30l3DA//l.QAqn.eZ08uT0/k  0~D/*(v/:gIDl3/ /{ X݋._/D0l380 AhD0l3Dl-(/l3:gI.DD(="֧l38/l-/nj0:gI_.:gI/nj'0'/l3x0:g.n//l.8u/0A09n-{ 1QA԰:0k /ԯj;:`/D6>0߮݋ll k 0k ll3/8u00Tn/Ԯ_6]<[/S3̯_006>T/8u/:g/_0mή:`e0l.D/(_D/ԯD0D.D/C!D.DDl3/l3.n/lD 0{ѯ߯6q0l.:gI/l39n-l/l3/l3.(v8u/߮Cnj_nj0/:gI0߮l/XO0D0ԯ.6/QA0l/l3/Dd/l3_Dl30݋/+0l//mN0:gI/'ll/njl.D 0(v_//ބC 0_l3/l.D/ll:gɯF0B~ :gIl3.ҵl /l3n/ 0l3.DMˮD:gI/Dl308u.6/l'0_l/8u09n-݋D.6/6>(/llv/ Fx0)(/(l3/(v0DU0906>0l.D.l/DD/l30߮߮_/pnj.!b/nj6>l38uT0֧/Gf/D._.߮/D/T/EԮ/(="QAk 0/l/D/l3/'00/9n-/گll3.l3l3/p %0ҵC ll//nj/D.l3//߭y ߮V 0:gI(k 0:gɮ{D/l/:gɯ'0ߣ/./ҵ[Q=E:`l30l3`ͯ/D0(zePҵN0EԮ0D60T/݋0 0݋0njT/T/D0nj-0&NG/'/l.l(v3֧l3:gɯԯ ֧:gɯl3.:g/8_/:gI8u/DDl8unj]00:`."/R:/1///:gI/0xsD/8u 0l_8u08u/m06llS3L./֧./_0l3DfDq_)/uu0.n_:g.݋0֧D.ԯ_ //D0/!b/D֧_0(ު:g/l3/߯8ul3:g.(/D/qx0lTl3=/(v//D/08u/6>l3ߣ#0./:`e0q0x0/Z0:g/(l3l3l3_Q/m/Z./'0_/!b0n/D.l3-8u0/50߰k;Ұ.8u/֧(v0/֧0D֌0<)0?l3.:`0Ѱl31l3/k 1Eے0? ߮o&:gɯ (v/nj_0:gI0="00l3-cW(0n/nj0{D 0+/// %0V0//mjmN09n-֧60D.ïEԮ0l-870l_V0X0T,/_mN Fܯ//(&x6 QAk >(/l/x0lM00l3l3_/ٙ_.ٙ0'01.6>(../\Cj; :gI/k 0jD:g..'C(v(vT/(D0ql֧Z.D/_/D(v/'0:gɯ8u0C.9n݋݋_-l30:gI(vDl./_/8u/cW0=00 /_Dl'0l.C0nj{ F0l.D0_/D/'//D.6Q0^.'//q0*/D0ҵ9n56> S3̯:g.l3/8u/c/D86(:gɯla^0l3݋l/80ԯVcWr/6/:gɮ߭݋/D/q/_/֧=.v:0/QD/l-/.8u/8u/'l3_:`e/t0D80:g.6>/mί//l.l3.+5n/D.'0l30X0p.:g/R:/5mN._.*'/:g//D/9n-:`察Vɍ:gI(v $ .8u0:g/D:gI/:gI8u0%/'9na/Gfmί8u/nj:gɯlO@0*0 0/ /گxznjl3/C 0:gɮ:gI/?6>/k l.D.p\1q0D/8u0߯8u/S3L0 DT,h_080:`/x/:`eD._80l3_/D0x0MK6l3.:gI/:`(/T//(v/(vk .:gɮl-/:gI/<)8ul3-/Zo&S3L/+0D/0//!bl.l30Z谞 '0:g.l3.QA0l3(./:g/l3/_/k TmNl(v'0XO=/c/-H/9n///(0D//:gɭ8ul-80/8u (.:gIï1SmN{* {:gI_D.9n/_/lD/_/fS߮߯_-(v/_/_="0D'/:gI/l8uk l3.n/Dl3l3nj/DԯC08u.s/_l30֧/D/mN0:g.8u.l.6k //x06D/.0(/x1l3/8u="_/0(/:gIa,0_/p0/6sR)9n-=l3.m0/. 0D//C0QA0..tp=lO:gI08u-D/D.߮x0k 0q:g.9n-0ï8u/:gɰ'0ߣ0lnj08u:gɮ-8ul/l30D0C/n/0mNl3_߮6/46/(/l0k 00V5/]S3/ߣ#0_/:gI/_:g. 0l3.D(/(._/D0l3._q//k 0:gI(/߯8uD/mN(vl./݋0l3k 0l6/l-D/6>0֧/:`e0!b6>l3.l3._/T/ٙ/109n/߮:gIl3 /l/Z0k 0=_8߮="0:gɮlj;8uxl(v/o&09n.//6/X/3HC/lE /k 0ll3l./l3//Z*x:gI^ު0l3k l3/mNl3 %(v&Nǯm/(/D//8ul3-/Z:g/D/D._/:gɯn/c/R:0p:gɮ8uD 0="0ު0./=/ %0=D_.l_.0:gI/:g0(.D/8u)r,,0XvzeЯ*0߯n݋/:gI_/֌̮]506>0m//D.T/l<-/(0l EԮ/ :`e/9n-l.D:gI/Q"'8u/n(.:gɮ߮l-8ux/pA0.xs0nj/:g/) 0eyl40_.D.D.cׯ\/~/ F0:gI/_0(6/T8uD6/l D/D08uk 0C݋09n-0\ 0D_/D/߯C0pj;_߮0/߯njQA/QA/6/ߣ#-/"~r3G8D-T/݋/l/DT/nj:gɮA(/k 0+0.{0:g/֧D/֧/mN:gI08ucW0ߣ0.c/t 0T/GI0$\/Q96/Z._`M QA09n-0Af08u_18u/8u/mNll3_.D.{:gI/-:gɯx/Z0(v6>mN0֧8uT,h/?xs/Rt-0l-D/8u/گn8ul8u8u/="0l/6/9n nj0(/n._108u8u////800n/nj_.l3:gɮl3/. 0:`*6/߯(/6>06/6/QAl3:gI('/%El) /8u'/~Rٙl3zeP0:`:gID/l/Dl,֧&NG0._l3.__0'8u-(C/XT.0:gɯ9n:gI(v//(/_/֧/R:00<0l30D/_0Qul3'0_/ˑ0l-_0="_/l6>0FJ%.\0/8u/~&0!blyl0="0k 08/p8u<_/'EԮ֧݋ /DDr0l.:gɮQAҵ"/Yl 0nj="0 %l/n K0 06>/֧1S/_mίmN0l8u"~30/ZD.D/T00 0x0nl3(v/QA02,/x6`ͯ/l/(D0l308(/:`/6>0D/X08ul30l/068i0x0:gImG毞.:gɮD/lD.50Dl 0/yl!b:gɯDG/="*/l/.p0xD.a0_.D."~_.l.֧(v/n/ԯ(֧0//Z0=mN06>/D.:gI:gI/8uv 6>/:gɯl0lq'!i//ԯ6݋nj/݋{0:gI/D/m/k //6/l3\(.mNl3,mN06/ԯp0l߯ 0ҵD./8uӯ(v.l._D8uzeP0:`eC09n/֧/߮D.{/C 0"հ /:gIn/k k 0C0/x0l3l5nD:gI"~/_k /:gɯ(v0݋:gI///߮l3/DD/ %}0:gɮ[/k 1PrR:000R:/\C 0l30 0mNl-!l3.l3/ F0/ nj/:gɯRp/֧550(v0p/:g/2,0:gI/Z֧(/0l/.k 'l.(l3/01:g/l38ua./_0v 0UT/(/D6/l3//S3̰?+/:`/(/ Ү:g.nj\C?00xs0:`e8un.D/ :gI0:gI/*0'/:gɮX0l3-6"'cׯ?6>6.(vD.aޯl 0l3.QA/:gɭ(vnj. F8u߯l3/֧/n/֧//T֧_8nl3-nꯠT.q/v8u.^:g.D'/:gI0l3_x 0x/(ԯ_P./:g/mί*V0 xsΕsϯQA0l<)0-//8ul.l3-ٙ/8u0.l30((vD:gɯ6l3/\0Ku/l/x/Z/0(0{l/p0/DDߣ#0(vD0l3.D/D/`Ͱ:gIA/_ e0[Q0.0T="0{02/l'}ߣ#p8uDn/l30\0ٙ//Q/D8us//Vnnj/(v06/D0) 9nT /:gɮGf(.D:gI/.a08un/8u="/(. %xo&0Eے0cׯ'/6>0E.x0n.D/xk EԮn.Ԯl/cW0l3'0/:`察9n/6>9n/Z//_/06>T,h0ԯD/?D_.//Z֧0 D.j{U/r/݋/ٙl3l3/l3/j8'.?/+(-"/֧É0X0nj/6/߯6/R:0נ/8D//8u0:g.(v/ F8u/l.Dx:`e0:g/00ҵ/T,h0_ 0.L//xsD-/گl.l3l380m/9n-0 %8u/߮80//C8u.l3/080Ԯ{^l/8u/M˯l3.k j^?֧/D0(/nj/.+0jxs0/(vl3.'k nj/D.D(/'0R:00nR:0_S3/ /:`:gɯD0Dl3 .p/:g,]/ /֧.м!/C񮨵0vHQA.J{Њ/6>(ï݋= //D/ (/p/:g.9n-A݋D=/'/D050%0"0v/l3,5Ev :gɯD,=/:gI_/(v`ͯ9nCa9nU"0-T,.$\ުnj(v݋'/k / x4yl4//nj.Ԯ3ȯ/Y/\/l3-mήL:g-l_0߮ %8u(v/k (v/忆4dV_?ˊ!*D0 0l..ҵD/DA(DmN(.8u/<::gɮT,/Z/:gɮl3x0=l.'QA/Cw<=6/l/l3nj9n- p/.߮S3L0֧,/8u0 ?00l3/XO0D.l-cW0/mN0:gI6/ %0?/k /_/֧/nj/EԮ/k \s|ٯDl3-/$ 0cׯ?Ģ/{8u8u/ll3.0֧0S3̮lqn/xl/l6>/:g-DK0k /mN0=/8u.\l3x/l3-09n.//cW0x/_:`/="/ C0:g.T/xx0o&00 %0eZ0+.l-l3.n/QAm/l30(.݋0Zh0/گMGˑAƯ5Tl8u65E/(/_/="08u-nj=0rn(߯l.(v_'(./50(v0k C80ٙg/j'/k ..݋_D0s/l{/0_16>/+0A/.l3/.(.:0{0'0<0l.l.\0H1.n/0/ F0Aj;7/݋l3D/_-_l3l3njD.8u08u/bT/k /'Dk ,,0X0k /xs/*j;ԯ6/A0yl4ٙ/v0.l3..㯆ҵpx6>0D0/֧/q/v.\\0.,/H\yl:`S3LUˊm/D0:gɮQ9n/nj/(v.ޯ_.l3-j;D.-:0k :g/֧/l3-A0D߮/l/(v/yl4yl4 0'//Dl3R:/ï:gI6/:`e/nj݋A0:gI/Tl."~/H1/R:/ٙ0nj/]u*^/.!ͱ .)(v.8050606.݋/6QAq0x8/\/`ͯY0p0./:gɮqm/ 0nꮆ504&ˮ:68ux/݋/jD/(v.T.xs(v/'0:gI09n->԰rD<)06Fʯ(vު!/n.:gɯl3pk 09n-/800._.ïބk =.QA// 0'}/(v-ocCZT,hXZȯl3_q/T,66> 0{^//8/"$wٙ/0l֧mήE.0nj="//D+/D/8u-(v\/-l3-֧/5ll3="/D/گ 0v |Y j/9n-0/Z݋]<[0=0//D/1//:gI/ /j;/݋5/E06>k 0Fʯ+ï֧. /cW0l3݋/[Q03H:g/=/lQAA\s0ˑ0((v00C %k /L/(T.l3/گ6cW_/E.l3-mί'/0MV1//hBx06>(v.1(v.0 %0.ck 0?0/߯:g/:g/ cGf0w0_.C/ٙE.0D- /0ߣ#PF T0X0/֧///D0Q0^0p/D-{/1ӯ:gɯ'0b#0+(-mήl3߭m/m_5/ 8u.l3_nj/'}/8u6>R:00*0T/xs0k r0X00rDQA/!/(=/8u/:gɯ/D0k /QA/:g.0\0yl40:gIeZV/vB0:00(v.9n-0R:/j;0l-cW/м2,cWQԮ.eZnj/mί_/D.([Q0k 6/߯l3.k ݋l3p//گ9n-/8u//S?/گ5Ev 0:`e.nj _6>򼥯Q0q0 F_/l.l$\0mN/q09n-֧1S0U/0"/="0D0p/.F`/_0:`/ZL09n֧/qD/_05/'0=/ F0:g-S3̯݋_8u/1S'6>08u/\s0=.lԯylx֯?10:`<)0T5E//l3/(/l?.߮mίx/=(vD5// {௞"~߮:gI=ïl:g.(v݋//گp/'a֧k ބ0:`/h0/:gI/D050o&/p0Dl30.yl0/Zބl- %0_/R:cW q0m߯/8u./lߣ#0_l3/݋:gɯ*\'T,h0ł0l3֧QQ0S3L00 (9n-.8ul3./'}/*.᯷x0'Tyl4+mί8u/n/݋߯k nl-:`ea/D_!_/l3// .l-_/l3-:`e_:g/:`e/kcW."/Űjp\ _.:gI<){:g. 0D߯nj{n.Dk /.o&0D./Z06>y0/x0l-:`/:g/k 0:gI0T,h00:gI/̃=0>(0D/S3L9n-////k  0/D.6880C8un..=8u/}^T9n-/(/5:gI.m6>/q/Y/0'Gc0ު֧._/k  0D/njn/sO.݋F=4/ïx0.//ԯ. 0c/݋0nj// 0/l3-0/040/Z/mN06.1Sˑ/R:///Z֧/7k jq\߯ "~/!⯾+/R:0D.{/ܯn-="/̃ %0 %l3-_-*(v.{="/8u0nj0x0R:00/Z.C0.:gI0.0Dl3/l,:`e/ %~&="="/9n-֧q//(vAFʯj;0mή/6>0+ޭ<'{0k '/nj0 00C(.l.8u:gI.߯/l{TU0v 0FJ0./`M6{^l0/x_:g//(v|ٯ:gI/:gɮ݋/sϯD.(l.:g.9n/8uԯުk /E. %/(t0nj./ߣ/q/8u>Naޯ8uo&=/9n-mίJ0="/5xs/ٙk =//v 0݋/x\sA8u..<0H1!0߶=:gI<;/ٙ/(v.p/l3-mN8u0м/o/.l/O/o//9n/l3./5ˑ/(v.l3.0'/ /MKD.{^/y/xs/?08u/nj0n.D/Ԯ_/D-D0 0:g/8uX(v/=ު/{ 0/𯞥T/l.://Z/D.֧R:0x9n-^/*\08u' /ˑ݋b0/DS3̮8u/l39n-R:l3/%09n-6/D/T/Ԯn/l3/_."~0S3̯x0:`e./Z:gɮ 0v0ll.r0v m/h$/8/Z/l-nꮒ?:`Y/EԮ<)/ˑ0hB0_.(v.k 0p`Mm./('/Ej;:`w0_nEےR:*/cWR:008u0 i0/@/мQA0 .D0l3p*v 87G8F1݋[0l* կ0WV0#1fc09n뷰' F:g/="0) $0( r0_0\ǭ0\|1m/R:00(݋00(v:gI/6>0 6><06>l.8u.R:/(v D"~*o~R綒Eے֧.`Mmή?'.k xsC0߯D/s/l3/qGf0k |Y0l3.?0mN0q/ߣ/,7ӮDl3.R:/\/:`.E>(0^//!b0k 09n/Q/qY0x0{^l0Y0݋0mN0/X0ު08u/Ү0_10.aM.r/ D/Cl3="ߣ#נ/l-qR:0.\:gI.:g.S3L8us/Cnm0:`/*0/0 0 %0T,h0Ԯ:`eE0(v_l3.mήx/r3Ԯ-H0E.0A/E.0'/9n-/E./y 0 ./D/ 0D /0!/xs0n''<)/="/!b_wn0\0l3/ˑ0D/~&cW. į:g-nj/8u.ߣ#/D-ބaUa^l3/+.Gf/ˑ݋C//݋:gI .mp/_-fLί߶0yl4g0p/ 0:`/yl40 0߯ٙ:gI(QA9n-\0ުF0֧ Eے/n/K/~/t0.ҵ+/gn.Z0i@0=0߯S3̯yl</mq0:gɮDx0/_0 g{08u/4dQ/'x//Ra/N7 %"~V$ai1S10/:`寋/TC/ F/.ު./G"6.9n-0l3(.0m/^/0l.x/ڻR:/5/h®?//Wbzׅ0@J/;T./.:gI/8u+0nj/T,诞V>0 {`06J_1E.0?MD8u0q/߮Xq0x"/ %ٙ.y0 %0/EԮK"\É,,֧(/8u/-l,8/|Y0+.n.{/0/Q 0H*00& 06>k /6>/k +G0_ы/4d\s"0?="/6>/:gɯ:gI֧.S /0E0$\0p0200n/0?0ҵ/8/_0/Z//o0'l0(0S3LD.{/C/Q0/l3-/Z/<-Q/C.="/Ԯ8u$\:gɬ~&0q/,,D.U=9n.680QAD/9n-0/'0:`//{Њ/Y0/C 0!b0="݋/.}QA/Vl3/`M0_.ުGJ1SMKX="/ԯ:`k ΪS/!b݋=/_.T/(k QAR:0^E./~&/ /R:0/݋'/C 0Tٙ(.݋/0ï߮8u/l3-87*U̼E߯/m/ߣ֧//ìp/50q08u0ł0zePnj0a^k 6>/R::`EԮ/݋c/̃/:`e/ Dnj:gɯx{mN/:gI^(-(vp݋/S3̯5ů֯(//'0l3-1(v/<)80D0m/cWR:/D/{/C/Vɍ/8u.0Cj.EԮ/p/ڮD0/9n-/=" Ưҵ/ /njބ0<8u//Z 700=/7 W0njί*/V(/xs/8u/0D9nm.ï/Z߯(v %(M˯>l3-^ذ6.i/m/l3-nꮹj;.\-H0l.,,_ F ._.<0y0T/(/S3/T/{Ax!/֧Z.c0D(/ ,60_-\/87/Z/v k !_/<)08u C x0x9n-'. 0|ɦ_1/l.//tg{0D/.S0_-="/5E0T_/l3.՚0q֧.q/8mί/ze/Zh0 ^ު/9n-l'0l8u/"~0ٙ/p/PY//x/_d(/honj/݋/+[Q/.]/p/+0ai0+/دo/:`DŞѯ6>="{/:gIު+//xsׅhH1pp/nꮎ 0:gI/(+="<)D:gI8up/[Q/ԯn/:gI0S3/8u.:`/q9n-0l30/گ6DE.cׯmNl3D//D/n/T/:gɮ߯:gIӮ?/fS >:`/Z/8u 08u9n-(.݋l.k /_.@J-/08ߣ/aiQAQA/!b00.0d[0=/ %//X0l3mN=.C/*,eZ/'Gc*/l3-Dl3=/D-߯݋mίj;/.8/'/T,诞C/ߣ#/Z̯_o& jk k 0v 0 .. 0D0.,ǭ0_:`e]u*//u\/נ/(0c?1נ0:gI/kcȄ Eے//:`e0/C/R:0/7j0(v0nj 0/Z. /l30/.c0+/l?FJ0:gɯ_/9nC/k 0T,诅ٙ_'':D5G:gɮ A=:gIV$5ů(vQAD0Q(v?n.k (l3X0) (v.6/a鯻\s/l. 0u0 /~/X̘/\/H1!j{ }{:`:`D.nj/.a^/*00A/l3-0L0-H0Q/yl/.v /.zeP<):gɯ:gI/D6 /Ԯ4/%U+0//mN6.o&0/l3nꯪ:⨯6QA/nlq'ߣ/ ~0L//r0 S3/ /'.'}0X0_1mD0KcW/< 0 /X0_:g./گF߭D2,nR ="8u֧?/^Cqaޯ k /mί9n.T,.u&ˑ/[Q870鬲 ,?//-%U+0D/:gI$\<;`̃=0'}'0*0 /֌0" 0/!0).^k /D0?/U/{:g/="`.:`-:gɭԮ.jD %B0+l3x0_(v/./گ/0lk .0A0ٙC/֧/:g.R:/ ma:g//&00(v.:gI/֧DDҵ.&D.9n.߯"/D/50֧/:g.t(-ȯa^//+ VE0D.R:0/(Ѯ="n' /'x/R:/t0*0S3̯8u/l38 -v^60(QAqZzJU0S3̯mN/-k -/'D.x016ˑ0D/6> 0 0./*ﮢ*0S/,/֧ٙ_.a/a0>s0_.D/xs0(. /[`MDxs="l3:gɮk 0\s9n /N0l/Eے 3נ{\C?0"~/R:/~&I*=0|&/q<6>j;:`e"~G/+0ˑ6>./8u.:`e//D._/\/.a0/u/Dt 0yl//N.0"ٙ8/+l/Qk0nj.`/ l3,108uo&݋/k /lS3L.0/ܮ/Qo&$\+.ajנ"'7 װ%U+l3-ߣ=":/"'8Dit+8u-'?0x/tk0{^l0G8z0a="0naͰFʮ֧݋S06,,0֧:050X0݋yl4002TfS20 0C'}bt4-l3.8]0֌L0 FnΑLN`^.ު9n"S3LzePmίl3.R:-ȯSdKq,0ۯMK./ew`hB8u.l3<cW+0\ylv/?O0%U/.,0G/"~/8/ /ݰaxs00xs0l30l/֧/o /ު.\0a^kG08/\0//ZQA0/6>0;҃0/A%0{oM/xٲME.~&09n. Ư>sگ87w0(v_1(voٙ/tK c5jmN /8u..(vmN88 .E?/QA?/|Y/xT,/"km0 vq.8u{ e0-)/뷮O@Cj;S3/D *o/;˟/~R0/:gI/-cׯlr3a^//?!.08ul֧/1SeZ000//o&0د߯*/ߣ# %ߣR:X_06>/l3//C0q/}?.$ =/0O@wn0 AK0S3Lj; =" <)/DqN/`ͯˑyl40l,?,z7k _0( Ưnj.Ax$Ù/ e/g6/gE/c`x/ުCq0Fʯ T݋ \0//ᯡp/.//<8uj;/./ Ư871쯴V(v/ /߭]<ۯf';+$*0 /g~90/r м/.E.0 0A/r/\s/"-H/"/8u87="0/&K0c5\sDMfLN0/9n-.ԯ5/X-Eے/6>נ/l+/՚Sl1l- 5E0w/:gɯ/88u/E00ïDj;/.l/XSlD߭2/\C//q/Rh00O?/@-AE8{.ߣ#f0 }/8u08u.(.l3.ބ5E,,/l3q0C /K="נ/$Ù(-.l8u0mN('06>l/.S3. /l/QA/-H08/A/n07 /.`/߯6FJFʯCx ^߯?x/b#0(v.mN0/龯*-//ˑQA1S/nM0r/+0݋:X08uO@0/1ծM\C+*yl/C 0!b/ު0/1//݋0 ,!t.-H/T,/?!_ 0/!b/0/:`e0.-pݯ(8u-//9n/\s/8<_QA0j/*o0)0h¯5nE0X0$\0.Y0`̯^+/.6.1ӯ偰/r_0) 0 0 0xm/hB0*oӯ0>0Hܯ0W֯T,h/֧D:`e/E./Z/05/8u.ԯ /Z) /Z(.V-x:g-0݋zePP^/l3-8j﩯#10t8u/7p\s//(q//*!/(@/=/ބQ08/D.XH1!/ze/./zeP/N0Y/*0v aM/Я) /X_0`M0B~/X:gIk q/<0lcW?!.7I*=ZH0ៃ/\XsO10k //ڮzeP(v:gɭl,a鯞 /v/ FW©/eZ/R:0m_10!/ܯl3.T,/l3/=.8u/cW'.uм/Eے//ԭX9n6>E.D-C8u6D.=x:I0QA݋.~&0.0+v%U+;:`6>n.="0 //_*|0Z̯S3L.cV$ QAKNw/"k .rm08ux 0QkH/^ QA/ 0oĥ0=/h/ߣ#<Ļ/QAcW l֟X="\sq'k l3.֧1-Z5/q.wn /?!./00&N/ 0Z0c0{0Ԯ 0 /ٙh¯qnj8/R:/9n{^/Gfl-x/f0ѯ_1ܯamL/ x' ɯ?!/p\A/n/X/|' Z G0/(/t0="/8uk /G808U"0o/T,.%U^rQ0G80_ ,60_'90:gɭNyۮbN0W0 0/{^l.E(0eX/c/+0/t/ 03~0/m/ˊwޯ {`/fL/l3-G/ݯު0*/{Њ /D.0.85Ů -/08r/n ˑ/Ӯ5.U/9neZ5ůNLE03/r!1Rt0`ͮ(v/!b:g/-/(D. 09n/_/Af0fLN0T,/T0Z0 ^00>(0Ic/"0݋ D/TQAl3'_/a^/ǭ/]0h0'G/sO/i@km09a/j;0i@0^n0/H/QA//󹩯.{@JAx8u.S3L0q/8EԮr. xa,00*/נ:`寢|Α/D.֧.T,/:gɮ{v 0֧/Tj{/'./ .(vnj.pS/?!/#/T.ҵ./>/i@0\J#0R:M020^d(0/U/:`e=/8FJ/H/@/&NǯDpq/j/^/l/ 0H/nj =">(0a<0"~/Nyg0@Jjl3 // {`D0ٙt݋ S3/xs0A:q錰m2,( F+X0nj8u.m/E.mίR:0֧..l[p0ҵ.DÉ/鬲/0w^D'0<)/!/B./^:0/s0Y?0/Z.x0%0o0L/0\0D.Kl3, #1 ߭/5/'/nˑ0-eS3̮43H{^찺cW#_/FT/. *Eے %D.˯S. įF0eZ//S0/*0QA%Un-Hq.a/r06.E. .h01Sx/{^/0L %a/{C /6>/ /!⯮hDp/6.֧/!/6>l`ͯIc a._0QH*|ٙ1~z. /nj.5Dߣ#8/.m/C$//Zðބ/owD/l3-!njR:0 2ݮ|/ׅh/ 0%0-C/6.-ȯ?z/n-!bG8r30eZ'...Tx/ %p. I:`e.:gI/.-5/:/"/ P0r3cW:#8fC'!b6.aG/hwU2;N.0ٙ/j{ٙ/!bw /S3̮\J/+/*ˑk 3H0-뷯!(@/]ܴ4/Ƣu"T,.l(v/;҃0m%//\/a/-/ܯ̘/w^/ eS6>x(/Dpدo&/^:wA-/:`//x//Z/D-MK/נC 08u0*ORJկ0+ /"9n.'//60Zz/?/0. Ư!ͱ00A/:`.݋.ބT.7/łn./ %/=-eZ.*X/MK/p/0r寣$گ(-EDpX/k .q/6^/K .،g"Ͱk .b#r %n/(ZHc09n-. 0]B1l/0 n010|_0F0Q9)01~01Pr-Dbȶ0Pݽj/k L0)>01+G000 ԕ0E0 D _V) iˊ!Y&TFʰٙ/Iǯʧڰ"'HChwհfLNuSj(yN0`/՚/}/F.c/dG(\n/6Y008uyl4v0=00u}0eZ0g0s0M06W0>/0~0&/#1010?0`ͯ1B1S/R:/@0w^/Z)0;0SV/ł/'.$%/qUݰԯ!="}^U^ӯG8/H.1!087/qHl3/ ݋_y5 %/}./ˊ!//r30o/'t/į)0:g/p.v /&2+0>ުN0r/0sϯ ҵ./X0T.zeЯY&PZzLX0\06'0-&NG508s Z}+%7 W0D/T,.l.nj/T0{x/c~kE80\9n/?.xsn6>/-/q/R-id [0ˑM߭T,h0aޯ:g-tQQ90:`e.X̼v Eܯv30՚0_ D) /()KCG/%". .[>(î ^0g1S3̯ 0'. eFJC 0ߣ0ު/i0Z0X0;0kD0w^0DeZ/mNC/hB/|Y_P=08<0Cw0sb0*06I1/Vɍ0q'0l3WZ1S0Z/8l-@ʯ~ҮDitZ̯ط/͵0V1_/rQY00賖.K' Yذo*V; ߬.֓00̃=0ٙc0.0nj/ǭ0X0U0m0:`e0z0h0ު0C /.//yl40֧/8u/*o/+/hB/M˯Z/vH/Zm:gIj6>2,l//kx߭[/ˑ1ӯ)0C,,0ˊ!'}0`ͯ8u_-ȯު/:gɮL/`ͯ*/p/.l򼥯%U/mN.a///*0 S3L/[Q0(v,#%0sJ0F10A0:`e0LH/D0 .FJ0'G0&NG0..,O0-0 )0v h0R:a|0*0I*=0hw/gC0AF/~&:gI0l0.0? Ư[[0^nƯZ/^5wn/0Z0lf0(vT,h0X0Ԙ<0.;10CH00&K;0.ea0o-ӌ0w."/wڢ0C0 0xs]<[ɍհr^[xް?xĢ݋C/z0J600/lf/MR0b#]=b#D-70h/:0No01Dm\/У0:00 /sϯ̃/S00PjV.(v,KUD)r04u& d0/P0Y00e0``/V0#TTQ0HlϬ\cpkx/0.D/0 ^!08u/.6J 02\d(+0{. /u֭(]y5cׯ?yl.8s9n--/0/!0!5Ic 0Q0ODH0>,/[EԮ/"/xs/^/.:gI-)_X0 1=/".c0q/+/vHz'K+00E./mN.$̃=06>0=./E.M^M˯ */fSˊ/|Oc.8/tk0WZ0(v/ PY0*(]0p/0~z0\s\C/_c׮cWנW"P>(/火0.*oZL0ުcW|&Hܯ 8uS=x0/_-{ 0y50/h)0 00"'0.nj.-B!l3, :gIC /îQ//8u䮝d`0-ȯ'Gxl3,,E0 Ʈ暮mO䡯/{.xs/="/]0dۯ{/l0:`寎w/ӯl3.5E//Hkx( 4zeЯ֌̯h$/>T0ԮDQ=/n0/LQA//دEr5.ׇl-֧-/Kj0w0& x-.RB0j\/ߣ1D.h¯ٙm/5EZz.'ߣ.Q0./n/ł0 0Ŵ/WƯD:gI/EԮ/ĥcphBfL/H**ɰ2Ű֧.( /'.\?%US3L-/)//XcS3Lfk LEےzeЯѯ//*o0//^/8 %//^0_0Q0q/_0ocPvN#N1i˰j+1".TGfZ°0x2,0l0 נb[/Vɍ/@0.0^5w/"'4X/<{;0XϯSdlfϧ/Kaǯ8R:0="y5/ =xAFѯ{NР|B?/..l/o*V0鬲JN& 0j+/E,8?/f@A_/É^?xve0>s՛//_/E/20'.Gf070:gI.د/^:05.T0l3,q֧t|t20+.c/♋[O6%0TJ\(0P0n2&0//Ѭ0B0S?EԮ/#~]0-/487,3m0ʯT./&NGa/nj$D'& A. >( //NK,1ӯ!0p\//ު F 00`Ҝ6qa۴_ـ^nư֧.":C "錰/(D-~&U^ӯ(x԰B戯v /Z.~&/3H/\.î|¯Q/Q/>(0mAf0:0<)P0t0r30D,Xh$*o (z/Ӗ0u/ /"'0g0{Њ06='0 ^N]>(m,֯')rjU //-+0ƯV/мT,$p}-mְ2[K3Ȱ6zzh0qZz/cׯGf.,O:gID׾?MH*3{y 0S3L/6%qڭrr/5E֮}bV/Q9/ |ɦƢG0wngl3_?-t$\0uV0. .֧8/0n/\.נ/*05E(0/í!R:01k /ު..330м095^JU/ӯݔr/l8sگEC0/,00M/g00(v}///0U^0E.0wn0*0g{0/{^l./0// N݁Cq/lf0נ..?0MKfL/Es0E/-0կt/Ŵ// %xsl4/̘/W0>/+-HߣRhs#/ /hH.0j+R:..qNܯ֧.a0J<F/h/(//%U/vB0HQ0a0n,fį)ůa.>/&0}^5EGfm?MA0.H/՚^㒧(-r-/08u.eZn1:0n/.Tm]-^E{0sO0;0c0a^Cw/Z.@#6/*/0 5-//V0z/Ax/v'G/sOU0 0 0xz0R:0. / j/n`N6/F0J0/D-R:hB/1Pr0ew060a߮`.|nw/̼0y5,, {//ĥ50m0J#/0 y/!0A/:м.k ݋/E80(/H06>-/S3/v 0g{0/o0/l./t/ /ߣ.E0V00[0XO0V 0q.﩯!20njCw<0~0 {-t`ذh®0~R/'G!DV /M/]/q-zeЯ^njު܂ׅ/ {/gEj0QR0{^lު0EC(00$0ԯUp.0N/eZ*i//n(~Ic !a.\/o&_gb/ˑzŮ0Ku&d/t=/Fn/ڭ*/`M0z70a,/1/Ht='/0͵(0T0Ƣ0~SĢ1Y6qa7) w0P1 %[+[:[w#0[נ=hv 5 1>(.Fl3F8/;҃Lg/.l/00L0s0I00 1*$0좚0:gIJU05/׾s/A9n-0$ 0'/PCV0D0Di. T /sş󻁯+t*S/m_5j;C ?-H8uUO䡰zG"0K/1S_-)ښ@J>(/a0 0hB/$ - 0~ 0;/QE0KM/笯E0-/ Y/|ɦD 0ѝ04/OE/s0p/.r>(AFqNy0l308u.G80﩮m/:`.*0fOi01A06//!X/Xү0x.QA.߭_//M0_0ҵ.c50p67j}w0. 0xl3Zl33/MKg/Zq'G.l/fLN/ .Q/?!Cw<0hB/0fS/^0B~ 9݋.9n-.!/ ?:gɯq.Z/ǛF/Wگ-://e/ !>@#0H12ү ?/łT-Y&0.z0n_08FJ/.V>נ_//Z8u >(/?^0/{0tk/{;5k .:`%.ZzKV/yZqU./ 0@/00]c0V0u\0C~/./Ģ08A/"0fLN0b0g~0P0o|00H1/'Gc/jD/|Y.9ˊ|Y{Њ6.C/p\A=;SQk/l?T,h.󇆰/e.~ 0S2`0p0L'Q/#!=6q0 -Nr9n-/mN/68נ/]u*0Dp.ϧ`/RiW0~ /.821/Ck /._="7DaޯmĢALO@.a/˯a/~Eے\J/F{0' 0c/R:0//ZnA0oc%c0!b.DK0:`e.oc/.l /د+.T0,,H1!08ur/G|'L/Q:gI,ݣ//nj 0/yl4jqeZ/ (<  ^!4/Y&5Ey֧/eٙ/xs\|ު %߶ުy İgŞQ F?/"~j .*v/o/u&0/ai//l3ai/$ɍ/O0.0ު0m/p\/Ӗd./V.C_03H/~&R:0p0C.fS PY{i /2"7/v--3^T\/<.ìZ(p///2+/ 0(-м/$d[-Hi/'R 1Ax0|/-0qH0$ //yl"~.Cw/?4wޯ8uew0 0V?mN/4 0Q/u /u/6J 0QA.Cw<08u-&0P=0X//}5ŭQ.Q0-P00)0-0 V/UU/7/a- 0/ĥ^0{0T,h0f0p0S3.kx0-/.V: tk/9n-0[9n-.{/vH0ˑ0~//10o.߮ˑ/ބ./ɖEt{^lî/(0%U+/YMWt/`0\./Z/]..al?87lD0l0Eے1Plf$*"A/ZB~K/8i6 .xs`L0.G.n.4MmVvBQRL/:gɮ-\sٙ~&հ?!.TQA]s1/t/X/ U"0t 0w/{ 0/".(.Lg .^ N0火/o݋.ۮïnj'GcX/]\J.ᯀ./y3e/\m/qE/a/WZ.'/#8*կ̼ cG8DpX'Gc6N.?0M/ _0[Q0Q; < 6-/8s,/qjeZ'/%kV$LK7p .c/?4cװT0a2"."' {^l֯,, 0U/hw̃=hCw</V>0C `M/#%P):9n-.@Jt0Pݽ/p*0/cY XC./.[0\گD$\g~9Xvt.}.}]~6/:.na˸(D=2 (la/ //V/Z/ˑ0="0eZ/p\A01/]<[00/'&.KSp9nh.//_ـ/)0;3~l5Ex Ʈߣ I06>-+_1.a0!ͱ}[T`/8/|b0l,eZS3.00~00hu/#5k x/]鬲{0/"6>.fS/QA@JA0׾70v¯l3-C /ia/\s&20z70Y02,08u.mNx 6]/[/׹9n-Cw<00[QNy/" Ư/)//^/3Ȯ~&0ު_30ٙyll3,t]0:`e-Jկ^h0"'L5.hB/6{//ߣC/)/G-Z/߮ZhESנGfe1 e0?h$0<)3H0(vT,h/ Pٯ-/fS3/,,/-.E0MK/c!0i@3ȯY/DEC0ì0ЯQA/:gI/ .P01S/(]0.o/!b0fS֧)/0|'Sd0T,h0?T0-É0/ˊD'U0.g ֓0/',ܯ.gEj/.nu&=-Ym:gɯ*.=׮DZ̃/eZ0ު/.㮗a0D/ .j;ů8U/t믥X./OK0Qm/R 10o[U0FʰV 0Z/.?!.0?/' /8/՚5E#10r >0X/ /0r3/fS21/ݯt x/F1/+ovOQR=/J#ٮn.:/5?/ίu&o80cW./. <;/U֯:ߣ#/10ŞQ/Aٙ-ʰMR-Ȯ(yNn/3.[/-?!.łtx/..33}I/훶')/&05E#1/oc%,?/賖.-L 0P 0'G&K/^5w/q.߯D /XE//rY/g~9[Q!$*$#1(~cWׅhTC/E./݋/(@/-ȭ/l?0./ߣ#'/3Ȯ)(, 1=0'Gc/A|HpnjR[0 0͵/09z0/w/!0įw#0tk/nj /Ǜ0º//9760鯳~k-/.=".Zzwn0(y/,,/r/Q.7ܛv¯r~h.k[0YM/;l*) kmT,h/gECUn1\s-F4կ>h遰wAӯI*I* :gɮo`<ĻpgA/+/O䡯/".C0:gɮEHC00xs0/_- ?!./m0N4G60e*0/|@0) /錯p?Xvn߯5Bw0K0K0qR:0/r3wc bw0L//I`ͮ ɯ=&bT(v/fLί .Y00A/Wb0/i//@A龯~R/jD/M 8^FBpP0/80W10ծٙ,="\/Р|\pԦM1l/MR_`L<ߣ.K/$/X֧.-/:⯗` ߯[Q/?)/kO/Ϛ+f00/0/Lk  e/'G/'G//8.njU74xs/:0]0aޯju03o0^d0p007t%08A0ڂ4/5Ű~.i0A0gM0bT "/{/qU/<;/D/g/="/ /?ͯ֌L/O!l343eZ/g0(@/=*oYî:/;˟/$/0|B/M//K/ڭ8NygI30JU0/̺/z/"0JE0 0`a0.40ad.g/6 T 0v 07 ׯT/ "K/Α//D-jZ87D'O//+/7p0*F0oM60 <<-+<)/:`e.8u\s$`W0Q//a˸ʿ@ܮ6N{Њ )Fֆ%//2//%kC. n/Z.<wk ,ͅ>+0L T / .eHb@z݋f]|0"~0<3Q:90KUį6D1xC0o&&0$*/:+/C`Ҝ0]e0njMA0:i0:/y0/9׏0w0M'0P= G0B0}ޭ/Nyg/ l/_3-l0l簝AƯSR:.Щ8ޝݔml5&"Ұ { e/r >0<$\."/XE0& /k+/E/|N/,f0/{Њ;/3#f0o0.c/۩/1s0V0 u0Y0f0=l3+ 0W)0.QA{\\0*0| 0!,;x00q/ȯv )b#C/YT*0!100{iu\Zuصρ|ְ#X߯t!1{iiyg 賖//(!1P/GJJk  /nj.=/(0/ ///AzS/Gf)/$/RB{͎0pg0/=D0 .piA/2). %R/b0-:07ί!0<07//Z0X/a^a0/{hˊD/*U3Fʯʿ@ZHAxp݋쯯}2E7Ѱ##IG-^5w/ )0A/!0'Ơ/x.ϱk:.(v-PٯU"T@.X:`e/ڲ/8i.\J/J/SKSlW(0e!G/tʿ/.5H20@0\/cW2W0:0/mέ 0+/jL//lM0 (0W).!08.8u}/hO+U^/+0:gI.կ /10b.ڄ 0[6 {`0G`.Qүl,K^Emz bQůZ 0$ݯc~zHQ0寭.E߯@ c[/*.&NG"b0/.+0k#0%/ì/;0=/火0]s//"~-/0wᆰgE/q/CIv /l30S}_.qfRaUZU0mdɯhwU"~{QAP.(0 %/kx݋쯕5X/nzۯs0鬲/v͵/T/ .aު^5"~Y#\G|/o&/ %.nj-π//`0]09n.20/>s/>¯,. 08u-:`tk_1/5.T,h9n-0/a^/Nyg0M0Zh/'}.0WV0/ai/Dt|&0x/e/80Sd1sʯXa^/- -V/:/-/Gf|/֧.:v¯t./Z/E.iۭ^nƮH1.O*//G0Y0ȯ0l*i⏰|YP?!./(ei0ł/ /ZIvBr0ҵ\~0*o/10r/򼥯q n/QEV-k -QA4m S.m/r3DpX0̃=/.9n/N/OR72/cpA0Skx\s.:gɭM./%_1 n֯?/mDmNh.gEj|ɦ/c/uZh/0;0/A`ͯބ?!.+.//L/_ـ0)0|\Z@0Nyg/l370r/z0W/C0~&/O/2//xs-ȯI3쯝ڻ0,F ͭ(@߭:0:gI-//h/ /aA. 0?0// "'"40l3a^,/p.00!`l/O/:gɭnj/6R:+ 0/-XOem D/ /+@0"~/0(@/v"/.'.s֓t 0,hR0|@ / c/?^W[b/Eے{/K`M//"M˯!8(].' b0/֧/|@0S/>D0(v:`/'/0W/g0W©Fʮ %.tkc?!bE/Վ00 F.֓{^l/-qU.O}(X#(/cW/o.{^͵(9n- T/LN/VW/.'/%T?!{i0"00#q|10w#/wn/t {/d[/^:0^/j/*ݤZ/F1#7. a^/Q/:gI/U06J 00eZ/=O!0/8h0~0ӯ*U, JW%-C.Ҧ<$\%U+(vEԮ/A0Q/ήD0寖.9SS>/T,h///1/_1/ieﯱł0/"'ܮ6/(,1#֌/zeP0I0У]0433헯 .fLN/= /n,0jD0x+/G/-8Ks/CXˮjT/lͯr3.ۭ6;//Cۯv͵(t/(v-/^/y3/j۫S//՛eC/.l*LU02.U.o80N녯 09#|Hi0//@ʮ`M.%0w/&/}01.VWo:Pݽ//3H/ %o0 Y-~\J/QA~&mί1Ŵ򼥯0%E_A0R1@:`.SF (/?dL8uh.v/Qaޮ$\+h/t|/0P0cp/֧/0z./m"/-..,/8Q9n//B~/0ÉBFJ{is0"~.l3+T7C&hB43u\0S0=/V/$*$GJB~//ʯ/mN.xU(v"w݋.*oGf@0v/40G0"JU{b800 d/rA/ f95^//Z+./MY05z.0.̨/0 Z/+Dk 0ŧ /+ .<VM b5r/s랯^/~&.í\ܯJ0'键Ry0n0Xܰ.h_Ӯ<e5E;2!0{ /Q0?/*l3+~&.0W֯x>0:.!1D:B,.D#$OR>/5֯mN.ί87.$/^)/~R/_./?M0xr.T,h/1PZ"寠T/;P/-Z<9n-!-X/uD.1ӭ/(/wQWsУ'n/JO8uIc 0q'"0鬲0m0g06,;00T/}T%rY <8O/H 0/e.6J/A/@S3- 0߮?//jï/R /^n/|08.{ ꧦEԮ.-:|Y`#.9H0 /%/.!;P9.zF1򌒯Qb/Α0.)5-DB"afPj|t.g0~ɯ>g0a,0\C?00/sO.ޥů;2*c>/AΪ/"c/ˊ!/׾/40r!*0үcW&0 /'0!(Ѥ,0w+u&-anR0,ؘDz/-./40h/S/G.eZ00%0U0QA+.l/|/֌̮lt0B~.n/./ W=N/z2.njmέ./}\$04M/#,4.\ //6j\.ATsʯ&龮_/yl40:/X` {^쮷?4E/.lNy0/֓/g/IP0N./Y/x06/<ĻCy0/j//\b0&/U'Ϊ@ʮ>/?0l3+Wg /fS(ǭ0oK'/3\".1- 鮢+>00'G}ǰ`:$\ì1N݋ˊ!2-ӌůC/}[d?/K1Kɖ0$ /-0b*龯;҃!0央od03/.C-eߣ8lU0HC0X/Ŵ/(WƯ'2//I40Wb/o.:0WV.Q90$ &|j/.ltk#//ad/u.DC.hˊ!/MX/3~:gɭ/ڭ/IP.V$y3rw/; uذ .!ծ(ةdQj; T wS0"~-.,v t|.?.+LN.߮=:/r饯/Ԙ/0dQ/0/żׯs/1ݯU/>$Fp?//e/M_B nf0 G/ ί Y/KU.x-0{I/1? 0P=䯂|'/5E95^/a+_.H0z0/_T/|BTK1:h0Yn/{{'RRa/ɮQA.aE/_1/1//00w0Q/T0/-;0D/S90I.0U"oc%WZ/^5nj0a`ylKcW.ZN/9r@/ 05)XKٯ&!3SZL/&KXQA. =W~/Di//֧lm=`0\C0^.ɉ0wf;V'ܯ_1'/:gI/&Nǯ.ìG毟e/J0G.Ʈ/N/Zh.ԅ/8/0Q0r3. ^!0 QA.C -/p?/w/ ,/)0x/u&/[QwnP=ˑ %0/40.$ʰt +q0n0BOv0V/?0Z/J.̈́$*Nذ|ɦc/n087A.sϯX/s/C./D0:b0V0,,/ad.0s1x/֧|$\.+-@f0G8/戏0/jƢ_៯/wװEے/{Њ0m.Ax/@J0 -: %/!0) 8':{r+/eB~ewÉ//tw.Gd  8i0lPݽ4sʯߦ09n-/]<ۯ/I30/eϧϧ/ .t/E/MKf'g0@dG:b/<Ļ.44vr/`#0Dit//?!Վ0)/T/^:0߮ .d[0cVf|Y.\J~I/ /3헯"09nc/&NGX00<)]/'D=/ί0j-rѯ]0ŞQ00.tl0 / j0w0909n/Se///(Zhwn./.cC200ބ/./ mN..o/n/:0 {'20C>m0T,h0BhwU0Pݽ/ҵ1njˊI*/H\//?!/6.&Nǯ /!/&˯.T,h|Y/0NygU*o/cW03݋.-/o.߬[/+.gEj0!/0 /䍛/{.."~gEj/Z}^t<)/0vw8OҮ.N.֗/ Fh$/Qk/moG8`0oZ/宍}/K/C.x./jg4/0t.X.y3e⨯&00)/-`M/L9n."~(įC/43!//ׯ`Md0&d08u.7ˊ!/͵(ŞQ/?/Ѯ.^.L+:. 0ʿ@߯KVɍR:0+"00ɿ/.l,&m)E0Dit' a,خ D/|0ktp#r,k;R/~Үl/U"/\|O090 .BEQ06/iޝv^1㱯x0=/A_C.{!f'v=-j@#0?ͯ/ơ/t*vlc /8.&˯< 0..gE/30p-Eے.s0-OQ(Fc1$Gs.2p\f/QK0gEj/g00BEQ0l3,rQ/qD'X:0/MA0./oc%/~/Ic Z.b${:Q0^5w0x|!03=/ ("~/0qN.i>05.ys43/wޯn/w/'/j\0c/Z0//e󅮯bT5ϯyO?}02ҵ-B/i7]ܴ/F{/ 0>0V$.0e/n'/,ڮ0J0 +0L/0s/o0/6;/y5 PY=$b/^)/a0e1X°= 0XР./f!.Y5?W1*-/QJ+-0fS2/!3헯M/xo?ͯJ\(_G0 m0+0.cp/fS݋.eT,h.r/;*ZT/*;.J\/(gEꮬ:0/(ĮŴ̃=./WÕ@JX0,F//Q00Wc0VCq/S3L/^/_/z//"~+oL.@֯LN`:.lm/q.b51-"1Ko0Z-8ɯ</0𑞮:gI.O@//q.1XO/zv #80v/j&K/ a-eY0o0񒯗ð4,0((^.:gICw/ /R|Bc/0r9S0 ^/]<[R:-[!xo0L~s0l09n-D'0{ iC-A߯*-/7X.40/g~9̻/d.V`+/\@έX!ͱzLٙ.OO.l %.(5.{0`㐰_3Y&qȯ?T'<6 x~q-ȯ:gɮZ.!0q0q/e/;_/q08s//$\錮6 y C.p\A/0;/t.4/8u.C/ai/m 0\|/eZ&˯qo H$.e0R:w./4d0\J#..r303oL/wC@E UI0ȯ(.|.~/bT0cH$ؿ'/u.>BRhkS/d@֯d8 /_,3B~  |rկEg.pCF0:/xwrH)0g_ـ/^PVI0A A//u ~f߶.hO0-/\/N/y/Cw<~/Cw .:g,i@/KY/.:R1V-4}Q?/0ՑX07/7*ϧ`8_?"xw0&^0t/|ٯwJ0)/Ю$ R/ :Qu.;GLSd/+m^|]/"+B/Z.)!/J106!/Uȯ+kZz.(د0/6!j۫6$,0G8.t,&( 40348_'/YC0iI/ 4<0S}.wq@/ I-.-;U(d/.+G8c[/ E//n.ׯRq-aޮe/wAxz/mN-K/\'fFJ/.vB//8u/Te/$/݋-9.z/Gyl/|]H/=BEѯl-I*=BF01S20H0龮0E//P087L')0O/5"M////8ͯQ'0l 0 xBM//A .x/3{y/]u0W֯Yد!bx.lFʭƋ._+/f/3 NI0/.,n-g0淶/s/*/>-W/:Ы/Yh.+iv0_<Ļ.S3Lp/l?0JծB0Sl0Uة,C0vB-ߤ-$p0)/[J0sZ/:gIln)0- +mޯUg3헯F\Zp (/R:,u+W:`l􀢯xs4M:9c]4P0*o/(0.0A..հzr/0q.˴/ρ0{0V/V$LN`0"~//%\0Ϊ/`M.4S3Lk \zv0 %//ǭ/:`1YCYܰwA-0l3-I0eZ/H b-0T/g.E/.V.a//P=ì{^쬌J0^m0"~J. 0S.p6?rѯ|Y.ί=}]<ۯ}.C0//4d ɯa@.K 0 {/6NCV`+07/OM|/&N.akǭ.XfQ)h$.@LƯ/Eے/#8/y5ϧ`/Lk 00Fʮ55j"p/..3+ٲnj-gk/5E.5@#p<4/+0; 6R:0;҃/D/%~ɯ8t|C P&/&0[/.%UQA./0(v,ylE0`ͮr/Sz4/ N/uDa/_gb/50//DitρZ)'.sϯ".j;/$yl;2:/M/ +@/ł.AGqRܦWA/G8/Y&S^XQ!/q_,)/6.L0i/WZ/=" 8&0n/T-00j׾/}ޮE.[Q.S/:/S.%%/^w/0'2/0@u05/{"'/<;8h0//40K/*10y>0[/|:{8շQE0ɕL$0L{Y0-0WZ!b-ORQ@(}\$cUz*/p.``/;u"1j'./ɱ(a1`< Sc0暰q!/tbg1/0G0I밈-0O50w06ίߙ0/1ӯ.80ZL.<7zr40ˣ0g%/Qb``k4n/P믿(0S:fLΰQI-J0x@?<\EK0.wᆯMKS~0E;90a,!=0|ɦ/(0.26,.E?ή~J/ڭJ#.Xl/}f0abVvC180d[00SB0ٰ.=j/q,ZL/>0\17/;aQ090Z'0֯|)M0D+}(S}ǯԯ=ޯ07C&Ux6/YANy/p0`ޝ-b[%[N\0#kn1Budg~7>үoP֊b${~$/-u/0/=mѓ_`8-QR/a饯{)>8/s0Ėv گ 5<06 ŞQS%0V/H*/̘/d/r/8./I0>(|.4O@S/e/t~/9<0[T/~0 F /A/F/M]<[/ISgEj{^l.ݔ/95/gE./&K/-q,0c?#1/M%0R0m8lV@/DCmέ5/.0N0/ 0R/i]e0/sP0v0티呰- 0cq0P)3T"< ,.3x-0/Dz4.Z,`R0*o) /u֯Р|ł좚/6Xͬl0ì0{00]9n-󇆰b/ު5PJU/6ׯhB.c/ /T,.ZL/6>-՚/d(/F4U10;ЯmN߶/d[/DX///ԭF/y5/ e///_30@.N?//J01Pr/v . q/㹰t1S԰֓/,, D/?/.{A/0>T0L.( "~^/0 0*$0y/t0&K$\/&0 b0E8c/ 0>sp/Qq*o&/;0T0磯Uy00h %0g0i[0/SŴ[Q/̃=/8/:@J//Z8uwޯ<MK/h50 %RD,h/C/ .2/ԯ/) +.5 .-:jD0//$0R:0Sl0/O䡯./$]'E95/mN.p606v?U0t//fS2/80yZNK,0̃1\䄰ȝ/ꮊg4P/6A.׾/{0gE/k0[׍8t/oƯa8K<+F0Dz0ǔ0(0A_0H06F/g<|0>Oi6>د񮻕B//ڮ-.MR&NG.ˑ// G8/^/[Q 0~I/VQ0]$I0H\|ٮd600M0T/^:ZhD/Un0/Z/{ЊZ/vHׅhcW./Cw̯mί090H/@.錯Cq/8u,4Vɍˑ0 ,6g/20:Q֌L./Shc0.;P/H-7.>̯Z,/M^0q\z/IX(2,03̃=݆s0$/@M=Ʊ{Њ.>®R8X08hR:0/r0w.ɮoޠC/H0A%/箧/e/(/G8/ //=/+P/*5&舘1.!]k0q@0֔/8+/nxsI.}qU]/ 20X/D:A. /tӯm-/Sd/Hܮi/T\/G/?7Ҕ.2(2S60\T6-// $6/ 0 .u֯bXf'P/ >{p_1.ѯL-PY/5x//7/<$l?.򼥭C /[0E:ͮn)n1:0/MP8 %.j/M.BEQы/.k0g/Ό90{^l-pJ00f0k06//X/I/.||/: /X0ѯg/G`/G8/Q/u/Z.,\0ٹ+0a/Y/)90:/J#/vB/\{"-Pc׮`.34/-=0Qx0y/cVf0/N#0/er0,,/e0F/vkdq/tK/1P//S0?7.Bp\A/U0/'Axث"_C/1.y5^ތ0/CI[60t)|/QuH\q/D-?/N do.$I ƭFJ.[Qު2s0 )1ɍկt|/6 .-/0M0;0e!G0l/l*B0="l3/I0$\.L /o*(/0zT,-,,qNyCm800'ze.Z/%ҝHj/8uxs/-:0(.gEipq/20=ׯH*0*oѮ@#0Uv [8m_uK$/׾7DpX/'}.EԮ¨0V/g1/{"0]0sc/ 0vH/Z0:!0lm=N/h®v /...c.ͯt.q/0#.0--Hg0/3ȮF1f0/ /0=/-:4/) 0lf/h® {.՚0 /E./X/uܯa?Eï"y*G8 /8.//b]J0'G./uKa0Sd/.u/h0_M/6 /5;00 4Xk fS2ǭ/'/|!!x,?O'g{ %R/ D3H/4jfLNS3L.3H/@0sJ0נ/9n-5.4/QN/bo*V$/fS01S0w0ym0yl4O/&dI"hߣ.&/.=.1SM0a,/a.6>-ȰX/"ͯ.~//î-H:9*.T H/R/i]01PDa^/&N."~/ /0 ZL/>0Α}/4FZĥìr >Z/:o03/ٙ.*0600C/0(/E/.MG|0V0a./"~/V$/0(0/ڮ"]/?!.0n/F1/m.]0/_0]<[Eے.>0:9)/ /v/J/j;/Ny/Ů//^yު/$..ӯ f-:ҵ- 8u.l3^*0m_u0/Ux:/w0-H*0'P=d0u֯!b/+//lM/_0i0 I0Y0-/QAGx00:`孖E/x\s|ɦ>+0/&-/k .MR<0*0^5/l3U,0ᯉ(D̘/-oʯsʮ#X/Nyg\/ 0ٰo0*Af0~/Կ(-+qX.,,/?./?^)į0נ.F0Z/+ԭ .sR) %R.ce<0Ӗd0E0DX.Ǜ0/' ix:I/~&J#/-0.X//5 .<))r/|20/Z~y!/E..gc^ cȄ.006/ήD'Gc%).e0VZ:gɭG/Ku$90!/{ 0_-CI0g$0xs.VJί@Jh_ـ/`Q0!f8@J./Y.0&/4d.#80w3H/5) "(]/44)rj/4/C> _1/1K0OR 0/.30d(/)0죆0 c0F{0_<w0jl3J\/l3+k ZO/+0.)/Dm_/9/֌L//S0On/1.k V/J#Y/VWoίK/<-/L/3T0V$0$*/c/ {-\Dc-5)W/"/ %ҮMˮ>j۫R 04/-H/#1'0w=^/#8dخ3+G!0P/F)Kt)oj3S/.?8o*/NX0AB0Ӗ/.-ŧ 2Nۊ/:b (0W/ү10 :m >(.Hѯmp/jBh$èzG2[#/10xt/0 /?+@0z츯WjgEj>BCO0"_C,!nЩ8*/ ,60 /[80H.ei//oAۯp/8&0/W/6U08u-a8 v'/r/ 87/0賖/Oخ̠/+@}.fS2π0h/ n{0P=0!b._.//Y%0|.h):`/|.Mpu"&.N/OD/ S.Xn_C27Q.,8//ۊɞh?0/;k/QŮބ-Z0)^i򯴩rs/t/QO/$L-/H-g 0FJ/T.[/G5/lx#1.J/w@A/#eߣ/K!0g|(aA/MIԯg!ZFsa8ԭ'u"/Z0=ĥ- 00K/eeϯU/Fm/1.rf'4y/X2&NG."/0/AF/T5(@d0>®/10ѯK.7 C0/A0>0uĢ."R00,/طS|0y..B2w/hF/2(0|W4$)0/O. L/-hZ'zg(a,3.V$/ܥk0c׬/zt/P)0/-"|//b0g0"0K'zg(0D0/o0001 /Ib ݟse/0876.)00;0k0/-/yj:#0ٸ# ׯLg/RkK0e.;aQƠ)x*Hү]0$\/x//q'W2RʯAү_2 +D/L0;60d/B~ /MQ e*u.Gy?K/g/d ֊/֭E.-|,-0@$0R¯Y0/dCҦ/;lP/)0(G8/ή0$#@0y0>.@Po2̯J/*N/CA0``.3 0CN"^$0F0ʹf/O.1$0/?T///t0b-7/.'p-]x/u&r$'0|E-|V0$0:1S/ ޱ̃-٬0>VͰ0Р|/0ݩc0\ ϯ 鯠0z0hG¯ϯZ/ݟs,/sh. ֌̯F/eZh_>B/-H 0/T00A˾0\/HѮrW0 %./Tj0 l<繎 0Eb.. -D`/T0˸ܯdۮm0S. {. Ʈ /C60طS0$/ݯ40|֮M0 ϯgsTGe{0vG//p/+00Sl0%5/ Y?ͮ_/7`fkAv{ y/[QyEL𑯈ٯ^ 06L/]0ȯ.//Y#a2/6د~fLN- rѯo/Y&/錯'M?C9/BEQ/Xvse0jԯJ-o&*/dѯ~&/3;Z/009v..S3/JU@/X0/ì/6 ..J0./w-H/1A#"'K0!0]=">(@#L [-H.BE/>/E/a,0T0*CK ,/5~( /ބ{^lz7ai.ͯLUO}ުn/Ax.|s/4B0i⏯Z/k/g}É006$0.\.x}0\BS;./ .ѫ/hJN79n--.sc(rY 0ȝI / E/xs-95^/*g/\,0$0; PY z70j;vv/6>.̯2򣯒6_0#Ԯp/կɿk;RODH.үa/̃=.}ޯd[0q../87-/l?.g.)/!/r7 .0j/]t0/d&0ٰ/Dpد_1%,0Ē36/6%0A/ Dv0Qu/ބ-/fS-m8.01|z0DpX/!-X/Zzcp/l8鮂:~>/'z⯚Ck - (/𢯧09pU^Sc//o,/?0-ӌ)r3.C./,0v.7/A7Q/ze.(.'2X06.4 Zz.^5/c&/;pLN>+t//)/N 50. 74 8P//;2/ \I08u- GSk {/=0u&/60A03"_/Ŵު- .;}/ e0O!<0fLN.[:.r/ݔ/009n/VZȯ /7C]4pJj;. Pٯ_?ͮ,p..s#v /(.n/̼ U6(y6.p\A/gEj /T,h/7(/yl4a˸/՚//*fSG!V00S}/!09/CD/1SƤS3̭͵(/).h0X&/5P0?/!0ꯩG.:n'}4/tS AƯ9n-06/;0K/j /0].GA C}{Я/vq;2*O h̰Α/$\.iI="mh10-A/(ݯPp=ɯ%)x>0+q/n0j.Zhj0A%.rx003U0ktZL ϧ`/BO0ׇ/QR/vrߦ/T/|/Z/*h­4N//I*0_3c/(/V$0b//q.0!NĥɍU0⇰c,.?gC>a 0 D "0/İU]a˸/Dr0F/X/Ȕ9:gI>~\q/¨/_Sxc/ /R0 0,,V.cׯl3+|(,8..l3_0CwT,hq0/ /I*=05ĥ5BF0l//Gf.H/l02[0FA0t.{P0|¯x,0 !y/O'\s.T/f0(X00yl߭y/w/0/0yl4/$*/.l3- GVW՚8u- D$9錯ze. ,/Ů /k0P0="->/L//̼b篕.0/ 0O䡯˸ܯ'G/AL5+0RB0خ݋.{/ /!.0 %4/kG0H1H\/|ɦ׼_0)00 ,0Ƥ/Ŵíܮ0#808..l^d0=/7T,h[/.a/r 0/ٯ(v,/N:02ݯ'2'}hB&0Lg0Gf/Mˮ[/[Q>T:/ 6>k .[3eK/\/>ԯwnk /w0^/ɯ/T//گ .㒧/gˊ!.f0毢*rGϢ0\ t 0k !b*/.nj.`MIc /Fq/π D-K0o (0P=宯Xp0r10oc%$/Jl 0ު/.ٙ-84:gIڻ0ܮ'0//?0B0/s.ߣ.zβR/^0}/?!./o 0mέx//8շ/nЮ/4O0DpXv-yl4.I0S3L$ˊX/~z0T-f/OM0t)0U宼ޯϯ5/ //^K0/0ĥ/oc. )0 q/鬲]<ۯW[ 6z08O/O /j{0:.m8/i@/^0O/q0Uί/|'/N0/+/ @0/`0Ditٹ+5)0۴//#70/S/]0 /r/w/-[N/Xʮ.I0//x>0hÉ>G0a/v*/j/cˀ !jIӯnT36)B}[.9#/6.FA/_7ϯX/P=/l3/Cq/iI]fF/"/Q/7t ]0#1tl.-/1Sn(0e.0I,H{`Dw/ ǃ/:gI[/ .mcƬ/E?ڃD N.@w/0} / /WX/S9(㕇`X/L t}CH2Hs/m/!2,0/f5+.◯A-F:ܯ/ήĭZ/՛Fm)vDL'mv .2!/0F/\0"&t05ů+//hu}k/k 6.LƯzv/,/鄯0c.Q /m.nj̮-4%/U0=?0z5 ).f0iCK 0!63ȯ&W0\-a,0 .4 /zN͵/e"3a$ĭ0E2/. 0?M0v?կ\󮍷+_Xίx5O6'}0Nj;.<.S ԕ!ܯ@:\il }/F=/>/Q/"L0C zxpleZ/K0}.]/0P.-/U0富-4J0e6/埯n1.*09T9//y0M/v/_/t5/;/ 10-=W6>͵bM/M/e%/:`嫂.ϧ`/v-0 Gù/4O0گK.F$0#0:`e/]8Oym/q[ `//@7 J:04\/8=/ /_fv/ 0"M0rT!/V0//)D//;g/'.g~90>V0/ڻ/݋"/ؐ//tKŮN"0{mа{.::F/yMH/Gy0U"0 㯲WXT;e15֯3 0!˽0u0 / 0t/Q0T,/ٲq-.d/|/%W0w0P/I0G0<;//01A0E-.{90Fc|ac/"//  FNK,/0l?a+/',\2/z/R_0i/r$0R:eZiJ0ż//J?!..FA'Vs..cG/i@/f%sc0ְ//\|/H/Up>¯G0:iX62/%үB新T/3 1(NN4V.ݯNy>Ԯ0{o&/,08sS0Z/A[//ګ /')MB/M!|2g/.8-64,//"~.ӰuXS;/ήCN/ d&q/"ln/̏.ũh/ g$0R֧/E0;0jq0ss0F 010xr,/ Q0B/1/t/fLN./~//1Ӯz2j/Ka3/ *//&/30c_"0(Į=$b/V a2C/+MA|//0?0700.q%H=׮/.hE/,Ѵ/ɸi0'T/ѰU~00mѓ/^(I*%., PYU.T/($/ ,6"/C.`//7~T/kxX/k870#//wy0I0!0P/Ao0x 020cW/R.//bf0x0_/AhBrު//i0u00r!0k06fUo07p.F~]/b)sVX/TN/X-/J20=/$گ...!1/>(0VWo^/L}I0=&0򻹰_3헮t0XsJ./OR<.Y?W &=&0q91.aY0~.F=|b0s0L_/ޡˮ,0:0H1.k -UB~/./S3Lj(v"0a/D-ͮop0ˑ/,ˑ//Vɍ/Ny.s/>(.. /C 0'/'6%_/^5:g/rѯ@/A0[Q.sRZ/$\.,Orb/uX ׾fj;ٙl3^ 0x.^0*05 mH// h)/Mˮ)0uu/ʧ0.XE(0/2篏0Q9<+/*0CbS0/>VM0Ŵk#0ZhAͮaޮx= zϞ/먒e/!1F=0Fm$0W0V40L/$yl/}-.Shʿ/f;m/QA0//|/ad0D Nm-Hl𢮞3.)K/ +0C/8u,;҃m / ߮.9/o/~/HܮmUˊJU.mV0B0@06> ʰJWԯ瓮0?/C/? B\C.-x/?.R!0yZ/>(>LB/LNS;ʯsϭ׼/g/{Я/$\/@ʯ.2[B&/~I/OR/tT\ p0[Q//BEQ/db-0ڃ 0/ 90g~9/i/./0mV|}q.ɮI8CH?/{0'70|-Ȯe. /}!bK Ữ.ŧ 0EJ#Y.a...'GcZH/񭋐0/TV(0.tT06,ؘj/I̯ϯ#//ڬ{џfmWU.>/OD@ض篔.0/=Yi cA&0AQN0/0/Q݅MG.xs/A,p\A560@/Ş-Tm`m/[C/c0l.0WVo&/)K%n/¨iq/|_0?Go3/-2[.РOB/l@0?ԮAk ?c5/֧+/n1/ 505w/D\0x-0znB.0xe)0M//_3.ͩ;Ή/T3.hʯ/AYU.<MAa^-.-6/bA$#@.%/';/VbI_$V)4/Ӯ .U/V//*/E0Y+-/p/j~ү\Z.<􌯅J/֌L/_',ï͹@20D@._//L//į(NޭĒ-0J#.K%ܮ0Zxz/Ꭿ:/3{y/Dw0#>(-.3/¯7p0/0=9.e9ٯx .R?%0-/%Lo/Q.1k//(S*0q#/t0|L/N0' yl.Zxz/f//YJ)002X ĤI0T,.Ė0ߣ !.^LJy$/V/K/{^l/ /(*fQ/!u/ N0+~I/_&/9Ͽ/)̯κ͆/*E/Bhޝ'gE//U^ӯZ/ lϯޯ`00j0kx.j0ˊ>(gnB~~ΪjY跮F&˭U0/.䌯/K:0/ 0 .!0/ /-0?/.r/\XL(v,D/ $毊80d~/'/8/RM+h`s/.*w/y= 0.m/ۡ/׎/Nf 0L/.Sc߯/^:'h$/D/PƯӡ/|s/y5'}/+D01.l?0O0?//gՑد/nʯ/~7/(/eZ/y\20R A"K'3]yԯˈI0bTNy/ś//OD/9h.oc./Et@#0 F."/錯 -TeAp\.$ʯuD/Et/C0=&/'.|/:/#1eZ8.̯.MIT0=;0/^/cW.vH/f0נ/ܦW0(tz7U@Xv/*0:?0. ?DZ9n.^ʯiS.Xy/r.xz//ѯIʖ %Ұr 70=]/h(0- 007.?ͯ 0xNy箅2ܯî៯ ^Ke#0/jrx0m5aB~ /yljC|W/q..|&/龮6> |¯6/U/0hw/.K.R HCÉ{^l.D+B"-ˊ!2[0?/a..E!6>/8 ,eZ0<j8)0ު/yF8//0M0`ͭ0Q0 i/ Ww0_Dit0ŧnjC2///bf(I'3Z/ު+/f/sS0/l?,/ Fx. >/U^S/g/ /A;!/G/[08u. 6ׯ%/M/[.̨/_X(@F1 D.,,SKJ]0q'"͵5R/䯗a9 0o/ 0x-X/?Q/D0ݯE/=;01^B0h_/{010Dit.nj_/Z0/Hl/sϮY!/sb Y=X0-7ݣ/fT/S/_;.',Zzp/vx$~/Rhk/``N.M /]/ܰ/k nj f0YV/L. 0?0c?/Ɨm0?/Fj2[/.,O'8iA).P/WP/ٱ/kį̃-./R/Z0rhu/ԭ%M/ 0GW.T/Jc/IL/.0 0/tϯY/0!6/(/"~|ܯ戏.eٯ//C/Q/6k]0ڂ4) R/o/e 0|r/SK/+qʹ0\|/+w0sQ=fj0ݟ.5xE//Q?/. /-/߉/_,Y$#@0\J#/ 0Pݽ.f0/N..7 W/T0Jg( 0p0D.U&PG 0e/00G/DR:=$ ai/OR/R:q/U/X._1.ilr0c~݋-E200 ^5wrѮ9/V00g>eî /T\{0p6/2ŞѰQ/sv/Bs/|)Mt6u"ݮ/#]c6zxX`خyFs/N60U/j/g.<60`</JNp>L./IS!u?@00:h/-`sJ?/#X/)/EIگ0"0/b"8iq0r\.ʔ00S&0./r/$! 0=W"_î.n-6p/kkׯ//1w. `.(BsMOO0PY.0_,\._:=Q60/`5;1>/K097.xo%0agPv;˟.$!hF0O//O/.K9/ F-87.9o׹/  iu/󆚯\BSXQ.0!(/0r3&zMPB0β3Eے/Y/N-X/r/a/q/\s,F%D0qv{ 0,I/舘Rhk.vv/nz/ODH/E 04:.js| 0ޥ.]/I/)O͈1 ߮%f ;p篞s1/l./f/(0Ջ|0BEQ/I0z/5/;GW= 9FK/;䯦}. Z/.ZB0 0T-/1/L5⯰/䀰|0-D0Jq0q0؈,0+H0m //-/F/4wE2p#Ɂ/Q 0A/D'/070K/.Α..ɽhD9׏/\Y0Z/~0X. 쒯%/t!.נa + /+8/I0偮錯Z.W0k/fLί\/3үj S]N녯o/&.8/X6/"/'Q0e {/d/6=&:ۭX/+0.LN/?/Q90_C6ίEtKޯV8u.Di0/1/d!yl:00͵/@/i@/ƇDZ-0.00W.8-Po!Ic .a/NO'D/P/c׭0hw/|Y`Z/YX0w0:/C>m/'.t0|@] H0(/ɞ/]<[2$/ Wگ";1>r /S3. /=0ߣ#O䡯P0$u/e_x0-//V,YD0.~R0u;0Q/ު/G8ְḯ!.H.1Cm-DQA/g/+ I0/%/K %0 q/?!QA?!.X/.0%Te//vj{L)10j g+:gI/3/`c?/EԮt /Cw/`/E.0"~A[0_05/}^/K/3~/`ͯS3Lr0.l3>(/B~%0sJ/(:gI.=oG8/_/K Ư"~Y0/T-X0/lQ믻\.瓯01⨯ 0K "00u0yl40%0i0 FE.r0*0rY 0y0!T,hwկ(@S=p/﩮4*ZzׅhiIN{P̃=/8<¯"..9.z0?MĢ/ W=0G0:`K/rQRcW=".n:gI,}Qj.ު.///^:{^/DZ/՚0Q90x/!b/ 毶/zr0zeP.tT/үC- %R//0 0V D'l3- 0- T . K.27"';2*0i/k6 /_/+o6¯l+V.Рp/0cW/fc /nj 0(v 50g~/ 0^/D.DqX 0Dԯ/;ZA+h/2/].; 0r.w#/^賖c.00/+q47.L//I*-H(H/Fʭ/گy/a.0}//~I.AѤ,0/'/Pv=iK/n.hB. Ư/ %-1S=_5 8u6+///<.ު/T,h//.O}/\I6;/G8/EI0կ /0/f;/4.=]1KZ#X_/50/!b.'06ί\aK,T=0i/-k0VɍF*0.M-X~z#ab/@//~/#1*tB1/m80{0F0/:g/Կ/,>֯,/׎0Zeh.\ȯF0Fܯ`ͭJv8-P=&[?-'?Iگ0W/A"0//X/k ./^:/:{/Z|ïqR://&40l/g&Q/-kv5苯䲯3D/QnaM0RF4U 0#. 0/t.+o/N\J#j0.rd/Y'ҵb0BNk/֓90i/k02/̌Y//Hơ0W.rn/ zT.0$/G8p?9#%/l֟/X/v.S6H0h0̯m.Tn1:/i˯S&0>//6G0~0B~ c.ۮ5/(v+6%̯00/2"/%//BZ/k#X/I/ f8y/+/寛G_0XF/7 \- /" 0[Q0C /zOu0د*-[Q/Qkhwկ/"~BEQ+w)S*20 V,!/C .3/=t.k/(rQ0/9+.{^.V/r/T-Αc{ //0 0S3L0)|YB/Écp/j;-// 0k.l/q l/MAEIZP0ni20/|@g0T,ha^W/A|ȯ0a^/I˂Jò/ԯͯ8uٲ\ p/yl4/c >(/A F%d0c0s"0S˯2"l ~үD&1K/Oxsq00/+@/&N/ {/*3!k ,N:/r01P/|Y.00|ٮ]06e"31Z/.nj/.oL:/~$ze/<;,!Qn%0:0SG0TCZ/@J]H\/̼ /Ku/%-0J<ĻF-F/0)/o&0t|B06kj/*0ʿ@95..a'}/|&/ /0/ 0MˮMK/(/LH;R"-58u/,,40 P/901Pr/ +0HC/K

Nyg/lRr5/ /0?/~k' I//ڭ0/0G" (-/.JnKw[/3. 1!b-Ax.'Gcnj /|+fz0G/)9/vB/Ms/į]<.H\./4K/] ]b5/3{y/6/t亮/$#@0۴L-00@.E( /4CnW0O/\/vc0gN&⭞`80.m,eRQE5Ro/%ܮJ;/?O0+,۴0xCz5/04vr8uD/90v~ 0/- .0ì,./;/ Ʈ-#}^// Ư/u0 {`2-0z7/ODȯv /ήį.'/u.; .XE.7sJ0.¨iG/-a.b0Rnic.$.MO/L 0< .0s<0S}0_gF/9#/N/#|0K 0U.N䯒?-l3*'ٙ`/4M03.@^/SjïM/VZ%bV/Y}j/>.Lu:0x/r//G/Fֆw-دu{dW/A{\x .T,-#X_./T9n ѯva2/].D 0r/&`v/Ȕ/I*=/|(Xz7tP0o0%5/Pݽ/$RB0CTjd/Ѥ,0Ӟ4U0vq//݄/;08u.cV>.XSHc.\/Ł0/:/Iyϯ𔚰j9/?!./J/!b.η0Bw//p\A/0z0:fA0%]<[-bZo/.+/v-?a2C墯lo//&dh|)3./(l//0WV"./kY}.~I/1S>W/B.33CI/ID0FR/0fd,*06t/4.g ,$/n1-yl4.5=0O0}t.ѯٸEî _ 0Ͱԯo0І/ȓM0Q 0qU]=ucUz*//)h.©U0$6/2#a/ZC/.ڮHa40,e|0 0C0h9P Q[O},ceԮ-g ڮ:gɬ~R.d3 E¯;j/BQ3[=]0M/7 /5?v0Р/$/=,8s.^vHU/  .<0.l>.4/06>,ZOXb--$.+q/Fsʮ6W鬲}q'@1:/ۮ A.#X߯/8i 0h/O@tS/ ޞ.Z$D'0󇆯~Si3/12/A媯6n0c/(njjDrn0ߪ+ԯx:Ig2g0R:0 0H*.,0frHQ\/^V$A D/vH,>B:gI "00/$Ùs/񊺯PY'P0A̘.:.p/7x-⨮l/0cW{Њ.@606$+m^0yvo0 0L/!-0?4/{k=*"4d2X8k/:ŞQ/qc/0՚?ޯư/.2-/@^ /+/%0rY M/ŧ ٙ,ϯ b{kxѯ$.!6JZ̭+/k;R0f7ǯ^O0=J-!0Pv/%080eZ*8u,tN0i@;0j0//j0P)+//گ4{0//֌̮$/ۭ/Z/i[Af/ÉT0/FJ/v/N Я! .0͡۰0<0c0-6%ҝH0ڻ3/(-|]T.iy-IB0ȶ/-.0_9C/z/ Į!b,ԝMxˉ/qH‰/P(t ?EO m 0ݵ񮲅O//Z/YQ?V/ 0}{/m./u.E8 Į"`kD/fU// ~/Xv-0.bƅ0o_0/(/.U/,0ԝ0j-9/>.0 0Y}/K0x.:/ڻ&뤯.C/CO/:gI/ί]u*/@J/=dyΑ.wJʏ- BEQ/=z/ R10V0~/3ɯZH.h)&~v xo3/.U$/20\Z/\| ed.>/ٯ'G/<ݩ0@o.^0O/fدbrB0~/nͫ//AC/y/TLB0l35g//I/v0x.~f0]e/0|x0r 0u좚.֓0/Ư.tzl/s /u&/wS0!-/hLx/rV /ODȯe(/.QC@/a˸.BX#00/!/ˑ0m0|B0֮' //!/"-a/B/1l-//Sӥ Qرl3.XT;/8/R / 0HѯdۮYhv .{^|0E߯ů />e0h/t.Ѭs#0Q /#_/_njSӥ1.hB/ˑTκ/ȶU0w5//X6u 0 VQ>H EîQ];k/e0!f'0+.k0m{^l.g/G-q0q80>'02q0F0 /I*.\J/=Tu0 0 mp0_/)0 PY] 2]s40FA1ì)1 0"oc%0ذyl0a{i1n1:Im^5w0JU04,0X#1rh¯t0of0 /ł:`e)1PQA龯ު0aŰKj1tEj/گ/wsJ~&/i0.20!Ⰶҵ_n.M0͵0l30/z0݋0/..0:gɭ 0v /(0 ek /گ݋É0K0v /{0&\|<+/Zl3 ~үn.ҵ0﩯 lx0݋`M}*b086>/n(v0S3L/X0 Ʈ|m/D) :`(vNyg0%U0?0+0(v/xs/笰l3-=9n-00 `Ҝ0$\ 4d!֧]Q4 ƯD-Gf/?l/0:gɮT2_r0S˰ 0fS0נ/<0//="_1?ٙܯO@/t0 Frܯ:gI/R:0zePIc0a0087n_0/.T,hկr0L/Y6>.r3l2/~/&NGy50//:`./`/^.V(0K0a^ބ?!.. 0\Z/:`.S3L/q/CV0/Dg{0m.n_Eے/߮'/9n-/// _,/<)P/D.8u 0Gf01S/./Q/!b/D/h/(vQA?0ߣ/0R:.D_0//݋/70l3/1S0X02,0:gI.k \J#0oc%(v/<)5/ 0݋0+1T,QA 70Jհ..0/1n-X(D0nn0"'0f0(v.)/D/A0ݯ /X0Mߣ#/k ]0$pD0r30\sҵ0 Ư_m.0ܮ1ӯ+נ/aj0*o0ew0xu\s/D-/;0S0~&0k 5 0n.'}0Eے/S3̯.0p/\mN.8u/..ze/ 0O@0м/֧/֧.&NG(v"~.l/'0 N녯ZLfLN0fLN0l3oc/sϯ 0AfD %087/mNު\ ^/ˊ/T/njnh¯{/ZL08uj< į8u:gɭ:ު0L/0N6B~ 05E/L06>/Z偰/?É/"0Zz/l3/eZ0q/.Q/y50S3L%U0݋0k /tD. /v p/nj06/l,ѯ./ˊ!0֧/"~o&D-T,R:/0 :gɯ0/D(v87.cׯ\/X0/:`eDFʯˊ!_fLN0ۯ/XsO:/t /'.'Gchx/j/_/l//Z//u./1Sïq/nj/h/:g-/:`e./v !b/C0+0r30D(v-8u0CxD0/) h/.:`eFʯ'/:/hB/D-6l3,l3/ΑD,֧H1/\/.a0_0nj0t/(vcW05/-(vo5E 0 (/a$\0EEے..)K 0X0~&0A0-H/A/կ:gI 0;0`/a/QA0.l<0*ݤM˰9n/8uqi{E0$\0>s0QA/(v87l(@/8Y&DtX/:gɯl:gInj0qC[Q0(v-6!/0~&0{^lQ90_09n-0.?/?/t|a0(.!b/0 0x0:gI-֧-Z/&NG08//v/݋/j/-ȯ(v/֓0~&0MKT/j\0_1/Dpد${.nꮂ|/2///Q/D../Ey00 00q,/E./V0]8uE.08hB/֌L66/`ͯDpXK//.]0>T0/0Eے0;M˯/l-0+0 (0:gI.ߣ#0/QA/ 0:gɮ/j0vXze.\s0%Z/*/T /.S3L/%U+0h/ˑ0Eے/X0/Dk .\D/j;/0KeZ/8unj c׮/y/\|0{^o&) 0Y^0 M8u/DX/֧j;x>(0cWD.l/./lT/ h0U"006ԭV$0=>(0R:/a{.|0k :gɯQg>(01T/Ԯ>TگG:`e/0S3/k nj8uC3//\l,݋u&08s0͵(s06 0?!./C/qȯ=м.a/+0O@0:gɮ) 'Gc06 D'2ߣ#x0龯دj{?!.֧T/6 r30 0./:` /)FJ0}YY&)110J/$#5v/ >0mNZL0Eے/ /Ny/nj01/R:/.0q.ZL0nj:gI0 / ߣ#06>xí0jzeЯ"5KfLΰn.8/e//'Gc0O0D*ٙh¯nj 0C ֧o6ԯQ90R:0X0\.O@GT,诅ٙ/\9nl3/n-8ުZI*=Zh/./'.֓00/S3̯0)k / QAބ6 0yl40G80b0ՎwD0:`eZ0JU0./Z/ %/50v/D'0S3̯ߣ/t~R/H/a/^0}.ˊ8uS3̯M/"5sʰk /x(-/8u/Zzt0 Ư9n"~/l+QO0_Q9j;/o&.S3Lnj0Af/(!.%U+0!bˊE0a^0,,0x/l3(@0H1//l\ 70z.0eZ0H\0_0MK0Nxs/b#ˊ/t0rq/a0v,:gI.Z/8u:`寸q="o&6%0'.c~&/m0^/x9n/!1S1/ cA݋/ -?/賖0[Q0t|_-/AA0 (06/8/~/K/+:0F1*U8.*'}/A20p/rQ0 D0aޯX/qU]k /Fϧ`0_/k 6>/=0C.T0)0D0elˑ1-/a/.l3ު'cׯ>(/a%U/xs/j\0Z0*o/ /l=":gIZ/8.878u6-łD.xs0>($\ 0~&/ł/RB0F10y50_-n0 /3ȯp\A0>İNy/(v.AL,0G毟8087p/a鯡pmίq6.QAl3֧/l3/C'. 0ު//*o/5E0Ԯxk X0 {/ 0fSl0賖0+0!0A/^x/ZfLNww0/r/ el3/M0}ޯD,/-H0-Hnjު/ 0Ŵ0N03헰1S/03/ˊ!0.Nyg0/گ/Z:`:`e/ϧ`0֓00nV$0ҵMnj48u%U/D ,60 .{QA.!bk sO) /^:0tc."06>/0mήCw< 1S0JU0.V/k/.nj$ 0mN.Eے/\/g-B~ aA/QD,|Y0Eے%0/@J/.l_îv 0*D/fS2,,/ 0&.="TD/h/l,0800l3[0*yl6.TAF)/X|Be0e0ylD20D-1S/D0.c0="k .a09n-/&NG0.j1k .C /n1:0ˑ0wn/\s9n/z0H1/ .*0fS2p60-Lp\'}cׯ{{ܯ:'{ 0(vï:g/0$p0/.60 Ư*9n-/E< (//%)}ze/yl31QACw.jxs/ˑ/="w^p/D-D0+D-w̏5//Z. įn /k /q=0/yB~  p/9na,/{Њt|/]j;.%U/0՚0-05E/X D.'0D- /{^G8/lT,՚;l,?8i0/R:0/ZL08/:`.|ٯeZ0_q.:`/8/w^0̃/06-v /Q:`e:_-$ Y&0L/):`寻\{^lV_Z诞.-Hyl/MK0+0-0נ/10C/ׅ0./?04/nj /l/-֧{^/ .b0u/k .Yh0 .1.(3U$\/el3/NQ/6.t|0Ql3--/="/!bq/ 0/l3-.r0:gĨ/fLN0"/H\cׯ瓯"0T0'/(<)Q/łol3-xm/n/="="<;*ުԭ (-D- %. F0A1Sk .<.{^lo+!0BE/j\"/EԮ݋.0QA/"~/߮篇m/yl4/6:gI./O/c0<)0n. 1 /$0,\qw#"~/0j/'.(0WV/(v/ ƮA0D/Z/u/ %/y$\="K./F{0./"6/609n.D Fyl4/8.c׮Zz/l30É/\/@S瓯$/_ـ0fS2z0S3̮v 00L/kmߣ#xs0T,/q(v.݋̰+0cW0( 0l3,/mN /8uX/n-8uX/_1>(0zeЯDEԮ/Ԯa F/1Pr0 F0_Fʯ/D.XDV$0 /.Q/ g0C/{^l0נoc%/G(@C/hA/O,k ZD/\lk /a/'G/:`e/QA/j\aZnj.F/߬5E/$0',,ҵ/E0x0:gɭ/zQu02,0Tmߣ+/ F/'/|//l3N0ˆ/(o򼥰A/!b/a įc/85並,,/xn^/՚/'0=02ުF2/=]11>(D0 0zePxs/î|ɦ.ߣ.h0/`ͯZH0MK0.q/FJ/$/6>0l/(]0O@/9n-QAK/< h$0X/k xsp_/wߣ/_880﩯./PY.,/*|ɦ6i@yl8}ޯa^l3-EԮ//O!Xt/430yl40rc6;0X/Xyl/m0_.pW[o^E.//:gI-="0D-/دd[0̼0O/%UC_-C h)0Ut 0&/.x/:0JUr![QT0l3Z߭x!1V$0ð_-9n-.Aưܯ 0ٙp\A/3xx(v r/R:6>'ުO!-H/./ /43Z/9n.l30Dyl/..0G./ҵ/V/߬6> ?M0+0./Zg0C0z.K'06/#T8u /T8MKT0q0/Zo&/6>/݋/ì(0T/(0rߣvB0CfS2 :EԮ:gɮ /op1:gɬNy/vB.c//7 /E0R:0eZ/m D0 0)/(a#80 =/3ު/zeP/^/!b/D'.)rLg/O/;0=0.vH_.:gI/'/6/"'r/߯ "C/q0kxT.v?/C0x/ڮz5/0k /?qR:0VD <.6>0Cq/ˆ0l38u.o&0D1/î(-w^p \cW/n. /?!/5//ުC.2,k T.:g, D0l/נ+/D/-/.>(0򼥯'x/aiJ\(0O!xs0708s00xsAf/6r30Axˑ0FJ0Qa.6 0l3QA0$/ %mN @J0r3o&S3Lt{^l/ ԕ(0W֯87/e0_]7 ׯ]/t0_/CqH0Վ/:`e'D[/'$p0.<%)0/l3/xA/60xs/8u.ҵ/?!.0.//Za_/7 W0o&o8. %נ ( IQA.lxsS3̯?ͯߣ.O0.80﩯k 0!A/tnꭞ8uX/ e0- 0ު/j.2,zeЯ'/="՚/T,/ (vկ &NG/l+6-50_-w:gI-X/ˑ:gI.9n& fL/j/#T>/5/9n-0{^l$*$دo="נVWo0C.*0U"0-ߣߣ/+0ů/s/*/xl|ɦQu/ZH4df5. /ҵ.-Hܯq::g-!0-wn6>/0WV0C /{^l40@/:gI./.q^0֧xs1HQ0nj.݋o/)/a.\s. /<)/(!/[/T?݋.9n-Zz/!/N08:gI'l,ˑfcłR:=.򛰮򛯓87AƯ8 Eے/5/Z0q.$*$0ZH0/h;~.;˟/eZnj.L/򼥯_-9n=0D|/nj 08z~ү.3/'.]<[0>(5E?/.nj/Za^ "~/!⮳:0R:l3:`e/1yl4M7/nj/vH3QA<).h.֧dѮ`LQ D/8u(ΑGf&NG.l/T,EԮ׾70~&/{._.5xEMK0oc%0F/%0="0݋//cW.,0G.Xt.[5E/.b/>(/:/m//_10*/QA/ު.̃Q/>,,/ /9n-n.ު{ 0QAC :46k .$ 0/"h¯ TE.$ j9n-D/7̰[Y, *֓00=-c5U:`e/:g/.D-H/5cWҵѯ~08R:0QA./گl, /5/Z/+X60EԮ.;/_(j;00\s0F/j;..a+C"~/$\mI*=0R:0/X/x/6>.0#80 a,0A//H/:`.s/'./*0/.\/fS21S5.錯QAބ/\J#L/0XY0/.м^/>T{^- fL/DX6>.!T,h//[.֯V0*V>0) 0+0E06/ 0=H*D. 0J#/!b.Gt0"~/߮lxs/o(//.l/="0/:`e00( Ư Qk/?0-\ˑ0!b.0%U+0ߣ.6>nj.//qY0./ɿE_*0~&) }/T,D %.- Ʈ5EQAˆvBůw^/{..>s/9n0Z/njl0:gI i6X0 .<(v/k 0.as/."'0U!/x(vP=龯yl/FJ/x0/Z/x/' /j۫/՚0/P0p/0u/]0f<)0 /|Y0r/(v.6q/ X/ %0W֯Zznj.6>/ΑO(@\ (/s0C /10ٙ.S3Lx.ު0./vB0*V (v8QA B~ '0 *0kK9X>Αxs/8uł/ބ6>./^:0H\/,r`Ljz0|'*1_0(?%U/ n0T[/\.l30/Z0 {/'/_/=0E0?//_/?M0\0C 0$\/`ͯAۯ:`.(@/?E+м/l+\1[Q&NGeîvKmN.-دwA/o/"Dު//._0/.ll:`9n/x_0n/,///.0נ/D.:g. %yl409n-1x0 .eZ0K0 /*/0/݋PY00c.'Gc:o(@:`]/mNE./H*"uu//Z̯I* /H\/.D/O/R:0/U/0hBxsx,,0]0xZh/:gɭS3La/H*0\{^/a8t믡/0Sr/C.4/a06.. ^!ٙ.x/ł֧-g0(v-=W6/*0T,读\s/گlު/!⮵xs{^.נaޯ ~&R:00ůg/&NGa^ 00"6ߣ/:~&łO@/݋.ai8$03/v//^:0+0/EC0"QA(X/݋.cA5ůl.9n-V$.ބnj/]S3Lh®R:0/Zȯ!b_.1ӯyl/xsaiFJۯSC /x/X%U+/|0="ҵ.ԯ:gIV$T瓯PٯXl+׹/v/\J#0 (/Hܯm.t0Ԯ5raE0/(+/ܯR:0Ax/Ѯ$ /w%ZL08/!⯸q.< PnjfLN00-H Z/O@-ȯ/Nyg0]/gE.ho.4V?Axlدگ/l3,D/\/QA/ٙ"'ٙj/j;K*0_q0/"8̃=06;0ުpS쯘:`e.A; F20\sD,#,,:gI-x 0ٙ/S/l8u/ܯnj.F0=-݋.%U+'.c//D. /﩯8u.ar0%UaEv/C H*0/Cqv /9n-/(0~#043!" FzeЯAmN&0T,hq0-3/H\+ a.x.!b //.:0n.l+/6J _,x'.fS2/40R:00%U/݋CwQ. m0N[QP B~'G/+02,0+/T*o~& Fr߬!. %0zeP/ٙ;0瓯1/-@0}^iìn/j0QA?!/.l/گބ/]<[2,/ n/'}.;00|&0k .򼥯0ND, on/֧!bg/Eےss0.a. .k .L.l-mN0՚0;P00S3̮/a/د v{-/< |Di]/X/߭w0MK0.寛O/ˑ+mY)r/:gɯ.r3S0L0/"'ߣ#0l3ު/"~t>05/fLN0-ȮΑJկQ/P/X$(v-.c/E80 0h/xZ̯FLFJ/_łU"0E./aE=".k /A0"xů/گ .v 10|Y/ml.ZL6>/߭n/`L0ٙ/.g//.O@N0_NC:`e m./T,hٙ.ުS6/C ~& .{EC/[Q05X-/Q﩯`ͯ.lDCq08uj/:`e %/mNQ/T,hk FʮD.~֧N.08uT,1PQAF0c?/ˑ %/м/j;/go좚0EԮ0="/L/0"~/l3@J0ܯ|Y0Nyg08uHܰZ:gɭ]P=0l3.C(vhX֧/9nkj;Q0k 0%UT/;҃/_T,h/(vj;Snj //ު0C00/nj/9n-0mί%U+0Jò0\8߯?C ݋0.zeP(v/x0806>/l3fL0$/ / %K'0>(0^0_0D-<00_102,0_ï %/=.c0g6>.K00XO0Tm.łܯl3/4_.^0/ԯ߬l30ze/4䰞 . F'08/گ68u/(v. 0^0l3:`e/(v// 0ln.D0D0Dnk 9n-l-x/^<)59n-/ %/!.S0-:gɮ/ߣ#l,T,h/6D.\/"~/J/֧/nD8(//8uD/ܯfS20R:0-^1SD 0"~/l.:gɮ87 x/k /0{l(CAFk C60(Xů9n/Z. ^8u//_ԯ9n:`(v %0_ˑ/ï:gIˑ06>8u.t0D.A0\0k /0="0:gI"DT,讚/R:00݋/ /0TDAîT/c/0zePR:(.ai/X9n/qxs308u*ݟ879n-_ުD8u0nj/:gIl36>4 0T/\s.(v/0806>Tc/9n/qU]0S3/:gI:gI..a//گD6\ /(v.="0l30xs.0yl/=/5E0<;0i@09n-0l3.:gI.ѯ n0k /֧Vɍ0Z.݋.7?0 /C'?:g,!⯇Q@J/1q[/$0l3-?n.njT[ {`0cW0(v~zFJB~ /="086>cW/֧.cׯٙsO/v 0ު0x0D00k ///.=".'Gc njl3-ł0Q/\9n.="0nꯟ8/_-l,yl/T/\s%UTF/ Ư:gIvnjp4O@ܯx/_S3̮al^0.k a6>-ȯ8u9nl3:gI.֧/*_. %0T,h0"C%/k D:`e/mN/"/n/l3.E.0C/H\="x_.QA0l8u/j;Dxmί:`./'/錰D %/n>) 0 %ү F.6>Ԯ$ $\n/S3//j)xk k nj/կ{^/߯뷯0Q0mί̘R:0/x֧ Dl3$9+0{0ҵ/l.{:gI$D/QA01KpNy/}1/T,h0)0T(v0l{ЊpQA Ưnj+9n-0S3L0=0!b*0(vބl/o&r//B009n:g.QA0-/.x//l09n-/l.=;0(v.:gI0/ZDA=k /j/(v0 Ư<)0p 0."/S3/ %0//Zr30n8u/cW/FJ0:gIG80[0l3.݋0נ/6/Z:gɮDuu8u/x.Cw 0x9n/\0%Q/:gIl3/c/{.9n-:3/ބ)0v/5E/D'.T,h0Qu010(q.[D/DDQ0!/k /k 6><)00l//l/mN݋//2[0QA/D.D.=0/l3/:`e.0ll3D.ZzQmίl38un꯷x0=/:/="/:`e/ /8uk .!/_0vBo& 0E.`ͯ,v \s߭c/'/\0D806x.x8u0'Cw1S0:`e /0lk *0T,/\l3/ԭcW0֧.!/ބҵ/) //xs/l3D.k . Ưl3T06>.N?0߯,0(00FJ0T/nj\/_/l3.D^l3-O0/X0D,R:0 v/߯:gIk /UC 0݋/ ,VlQ0.a/:\8u/.3T,/x/bT/݋/30:`e..08u/\0nl3/i@QA00/:gIQ.R 0!b/50>s00/e0.:gI*ovH/0.נ/:gI//= /T,/T,h\/DK0:`e/8u..R:0qq80:`e/D$/^//Z/l3FJ0v(6/l3.87:`e/D/֧QDoC?AƯ n0/x/k q /ު8u/֧/mN0'zePנ/0\x0V>S3/j/ ބ/9n/w/0'/..2,8uo*V'Gc/6@$"~Z̯'QA.㮁nj_8u(v/"~00="/ԯDx=/߯/Z/C{(v /*:gɯ\0"R:="#Tj;xs/2,06.a0/*0U0*/0l3`Ml3-/n.8u./(.:`eq000:`宥X0l3D0m"~,,>(/Dxs08u..jԯ.a/w}ޯo&yl48u.-{_.8u/R:/ R:0,a^80EԮ0x>(0p/6/D.ocDł{0q//8{0T,/l/l3!b/4V$9n-Z֧.x,,0A6/8/_10ٙ. %nꮻB0q./l35/0uu0j.q.}0=x//56>l /DR:轰6>C5/ Eے//{~0nj'/n.0T,h0ԯ6ѯ//0 //u0njq0D_0D0<)0xs0"/ł05?/:`Nymί(C //l3="/fS2tn.QA/~0:gInꮺcׯU9n-//Z/sO6Eے=QAD:gI/ٙxsު0^0QA0l/֧/6'/O!/ /ï' 0?!/g,,+0q/nj/="06>DïD*(v.:`e/-D/p?݋/U_-*-H0߶U0x0/3H/Q/\sZm_3x0'/ٙ/zeP.a0/S3̯/&N/T/]0x T.al38uj;lPq0xT/?0 0\/ ="//Z8u, /T,n?0a/:`/Z/+0xn|&/W)0zeЮ[Q/P/<)0`ͯ0j;:g/ѯ+E/D.// {௩0QA. F6?0l3/:g/:gI.9n-0+0h/h0KuQAl3-J#YeZ.Vɍ"~/2,#'G./JU08ua鯪0+0r0500 %0:gIh¯L /A(.m./_/!QD/0"~0x0D0^/q/'/j;0!Dlo0?M:gɮ:gI/E87QA/h)/ xs0l-.l3Z/=&050t:0'.SQAyl4/nj+(v/+0_1|ba0 .:gɭ %0g{/0Q9:gI.j;0^/j;h¯k &N/Ax0D݋/l3k //_/گ:gIl3.R:02,l3n '/S3L6>. .C ߣ{`D0="֧8u/ 0 Fm.!bqмnj\v l//50ҵ.kmQA/~&/1/y0".1.:ު/c,=/l8u„0QA//pa/Nyg0=.f0:g. j;j/mN//8u.{.'//l:`e01/K~&E8j;0XAXfLNA-ުD--0:g.0ۯ(v>TK/./:`ejJ/D._ٙ6>Dj/%/Ic %G/%U+0o/lN녰"'l(.l3-X0 0\s/ѯ'G6>/0S,/'0j;87+870/l3.ߣ#006>/6>/) 0k 0_/ˊ!0t 0w"'/:gI/(v0_l,o_D9n-wnlC/ 0l3. !/R:00T,h0x+//(v//D00w/j;0_yl40L/Y005E֧S3/~!/݋S3̯'}8u/l3:gI6FJ[<)6vBݯ/ /k k 0nj݋Gfު/뷯/Cq0aE00\s/i⏱ /?!0a^/8uZL/40.6.:gI0m/.?(.870.֧/T,/N0/2*/7Ԯ500QA0QAveZ0. / F.="0.zG:g.֧c/Z0nj/8/6xnj. /ˑQA/lZ诞!bnꮳ:0yl4o:`C/\Ic (DFJ/D-:`/0."~/-N0lf0 0/+0/x!<0.lgEj/-/-H0="0߭/[0 /S/x/./9n-///nj/R:/D./'T0x/Zުl3_./R:/8u/D C9n/tDQ' 0:p.=".G5fS2/n.:gI/ .̃l/^ԯD//qUݯ-x _10:`/ . _njpߣ#0h¯/گ֧5E/MXR:008u:g.R:/T,h0l30nj_/֧6>4龯z.|'0Q/6/)/ïR/.c0"'0?r30:`e/m/9n-.D/ %xs0.A_Kk /8u69n-/DA/~&08/":`e/T-/~/9n/b]Jnj///'.n/10]08T.  D0(9nO@./lS3̯8u/8u0Oa.4dX0C _t0֧.9n>(Dr0_DD;҃/8u/Q9/.C0D-+/l/:gɯ:g/l3/ 0-T/Ax¯l=l3+݋$\0 08u3''C 0/yl4EԮƯxs  0/8i/ܮ:gI.yl/l,gEg5OQA./:gI95^0nꮟٙ/ٙ.D.8u//_-ځ0l'/ު:gI.D-/l-DD-9n/ïðT,h00ٙ-/:g/=/yl/QAsO0ބנZLu\/9n-/9n-(v/C/:gI~&߮aޯ\D,EԮ/\KZh{X-ze//Fѯ-T,hl!/'L/0>(/Ak /.pxs֧ˑ/n/0n..:gɭ9n-{/m.-NygDԯ]DfSS0l,/x0p0ˑ0݋c. /گկV0cW0l3.}{/0aq0ބ/_1/a85Y0 %mί\j"l,:gI.mήk /QA/ 0l37D.._/.T0Q5ů̃~&0m/8uj//9n8/*%U+0k ="0^6>0Ŵ/D'Gc-\2,08u/Z.x! >0\J#(- j;/.o&0,,0C0m'/o&T֧E.(FJx/._C.(v/0l3T0N!/GIMhw10D.߯Fm:(vmN/+ [0Cl3DCw<\s/c?0/ˑ:`.c0/.mN.CqA0:`e/[Q0g#10k' %/eZ0<8u.M˯fS20\s)/nnjX0<)ǯfL//^:0p/^//ڮa0Cq/cW/O0v/.Q/a0R:9n-.q E08uzeP="(8uT/^%\/ %0?0.0%0@J0ׅ/q0b#8uۯ2[M//Q t|C/݋k /_.:`e/ބ:`e"3ȯҵR:0:`e0ѯEے/QAXvԯfLNc.Aq賖yl/կ{^l:gI&NGL/E.Y00Zh/qUݯ 0 Ư:`enj8ulT/._-KUD:g/ %/l:`e/,,0ǔ0k .q/R:/c׮m/F4Ur0נˊ!0+0-//T/0i@."M0"0mN/_(v6:gI.k /l3.1S0_.݋~&0r3ߣ#k :`.h/./`.~nj.c/:`/֧.߯X[ԯ.lÉ/8/(/ %/ѤqD.(@̃=On3Ȱ߮xs8u0lZzl3_S3LmN/D-T,诺cׯ/D %0eZ/ł0d 0&N/:`e0.c0/6/Gfïn'!`010l/'}D.ބ0Վ0Αl'T01ӯ(:gI:g/}0É0nj/-G<v/:`/(-0W֯_0֧:`e֧.6>k S3L.(voc/`M/м/k //n8u/_.l-.yl/P 0eZ0:gI0/t/ބٙ/D<0"~/ 00T,/:0{0/=--6 /l3D<)ܮм_0*0/ބ0 >(/M˯^e%09n0njS3L/,/_ـk 0q0ҵ+SwJU$06>P/v݋/v/$ 0ު/-/!0VWo0fÉu/ 0/ZE0//`#05.^nF08u/9nv'T0{^/D8/8u0k /'}0\s/(v9n8a0.8u F09n/2,0kma8u. ˊ!/l3-/o/֧.՚<)xsFJ8/D,+V.T:b0?!0oV$.nj/ԯy5ҵ/\s0m/,,njS3̯ W=x/S3L0ïR:0#/6>.k0/KuEԮ.É/0870.3/S3/6.0/^:0o0J(0 T 0 0vB0!bnD0E0!y0,/C/ǭ+03ȯ:gI6>/0,/:87Z/<)0_1///a/#8+:`e(v\sAD00Z<0]0 ,0g{!` ('/!m/U_V֧xބ:gI/40 0D/Gf9n:`_yl4=")0S00yl49n{/:gIe0qH/,,0 %0/|ɦ/6j;0:`/5]Z08/r30(@0D(v.V/.DD,R:-x nj.lD/o0.0F/o&:gI/ /l3!⯾+ˊ!/1lDK .?ԯq/ٙE0E.0xsL/r36>.l-qn.9@0ԭT,h/:`..c(ve/z/\./(l3É>)/ T,D/t|U].(vv 0ҵ/06.T0Z/0-04 ((v8u/(vR:o*/ބ/x9n-0 Fl3.(@/:gI4/K9/A"0R:0\8S3̯ٙ/ /FJ/K0M0x//(v/`M0:`/S0_t/nꮠTDmN^\/V0v *:`ejS3L/j/E00fLN0a^/="0V$/E0.QkEԮ/D-MK/l3-_.l8u.H\!/ F+*o|)ͯQA/..>S3L /{^l/ {`,oFJr0 /k *.vB0 0TL 0/q70݋/8u%0o/F/ Ʈ{^l0.8u0xsv 0y0/T,/cWˊ/cW/60080a/?M0j۫/'0Dx/D-t_ـ0 /%9nxs0(v.`M.o.C/-ԯ. {|YC$ 06Nyg/8u.>hJ/'﩯 L/(/ҵ("~/Z-j.;҃:`/C/_-|.x+GJ/z7~&/mN/:gIQA6>QA6fL/0D0_.X0+.DpX0*8u0lD.A0>(/x.߯6.D.Eze/eZ 6c׮Zz/36>0=/mN.k .;/q/.,OIc%0=":gI.:g/2%Tu0?!.{נ/yl46;/fLN05/C0/A/-/:gI0]0 +*)0k /.n-/lٙmNTeZ0W/*/o!b^//'.OQA:_g/D. ƯmίD/\./ZLN"/o&l3/د:gI. 0oy/\s: Fl3p/ F/.cD"/q/(/.nު.A8uS3LD0mnjDER:0\C.a80r򼥯{^l] 0jԯ[0:`e//*///:gI7C&0]N7火/A/՚'.&/%U+//ZL/="0 0xs/ު/Z/ܮ<08u/Y05/(.Sl0a %.(ҵ. -\C?0A0{^쯇m|0?//:gIx/K.c/Anjl?0D0 /l'. ;˟/LK0R:0/:gI0_1{/lA/xs5Ů֯/a/+.QS3LG8 S3L{^l10݋/îpH*8u.J//Z/A0~r8/ /. 0(/x3~0cW/{^a^/e{P0'0+fLίc__. //G殞0'nՎnjD/j;/l3xs/AM!0_//1/p?07 /?.o/_Q0'.sc(.8u//Z/T..G (./.Z/9nT,֧|/X/8/Dk c׮_//E./EԮ.:g-(vl݋.=/+(T.՚0aiDmή/կ/_p6>8u/n:`e/:gɮ62/נ/.mN */q9n-0֧. 0 {^/:gIv /_/.mN-/%/8u.cW\/':`e/݋.hB/X/(/6//^:`M/=W"'ïxs/:g.TlD="/="`pr > 0x=:gɯ1/"'0/mN_M˯,\ԯ֧/߯ˑ(v-"') +./:gɭT,.Eے/xs!]/S3.v0.cկjfS20t<.S0*-?!.8//AMKnjK0D0$\5+ٙ/^.+08u.(v.5.o&/tk08C / 0xs0{0x/'R:/n.6D F) 0ai/EԮEԮGf+0.Tv/DA/bkx8u:g.D.nj'GcA/D.T/*?nQ0&NGy3ep(-?/ /l3(.i /{0 .ߣ..l37sJl3k /k 0S3/`/"~C0aޯ>VM0#0phB0_-]vT/HNy./Te70_@ 07/"0c?:gIzeP0X 0]/ ./ڄ0q"N+D-C0\C/:0ylބ0V$lvtӯ/-'G/m/&0u"0@/u)0נO!Qu_/nj./ :g- e0 0m-ˊ/^/̃/nkZz.8uN.ԮïFJC/ٙ/ު/=0:` {`DX0/:gIla^0D"~c׮/V$0Ny///ڮx/O/h®5P0ҵL/ {`1/h/Z/1/6/QA0{^b#/t:+._/(v-ҵ8u0D/?H\D-T8u. /`M:`/ڮQ[Q/#T/G80.//Z/+0-^/8u.:gI//Y/XK0ïD.ߣ#/\C?/DZh/Zz/:`el3,/3H0-/ˑ0a/T/. F//. 0/ai0:gI.5/?/b#0xs//(`M4䯙I*=\J#V$v(.֧.p F0.v/:gɯ~o&"~/"'.l/87W©/UhB1.֗O@ ɯ2FXG0./Z/|0-H/(@/C:gɯT,h0(v0֧=݋.vîg0.c'.`ͮzePm/9n-fU0cW0/l-/p\A0É/mN9n:gɮgEj//'G/.ᯠԯT/0/X/'{^_ܮaޯ8u.x-./_ު/D.l3/\0)0a^8T,hנ:gɯ.a0/yl/Z/q//ze//j//8D.l-9n.o& ="nj'"~{^Վ/R:/D./{^.l,pCw<0/ 0/.Ư_- -H0XT,.<)/ĥ50mN..l//e0l ,6DD/n.D0x/ {0f0!yNyg et/mήmN %R05E.֧&NǯZ̯cׯ{'Gc/O@@S{//nj ="8/9n-נfS/^/R:/)="K1o00x,,0'Gc(ު0nj.?!-H0[0.x 0k l30l3'a.z.?!.:gI3H/+0"'0l>0l30k 03{y0T0JU0&N/a/ 0(vw0:gɭT0./C \s@/9n/y'G/įw^P 龯(D_:gI!9n6l3.zeP_6>0(v///$/9n-łm-r0ze/87.c/S0(- zv0/.:g.0/6z/< 00ZDED//򌒰l3qmN./-j.k :gI.{^l\/`MG(v./) 0:gI/.N:`ex.ᯇm/aaޯM0՚/TnjE0l3l3nꮪ*.c+ "~l3,jk >0/ ,60 F LDl3-.c//ҵmίzeЯ򼥰jm0D70t:D./xz/گ5m/Eے/l3(.8u/ . //FOZ08u/ %݋m//S3L0!b0}0QA//=.r0S0{Q6/xGT,hٙ/ >0/Z0ﯞ/r..U.4/9n- Dl3, / /8*o0zeЯ."./e(v/!FʯYh!bބlP=0!b/NygqqB~d[L0Ku_0D-/گw6>(l3//fS3L.v /p/V/ 9n0Ȯ 0CF0QA-O80(.AX^E0 |YC 8/FJ.kxY0%0p/Q90qNy)Dmί/ j.nj0_S3̯ /D//XмԮ_/ Ư?0q0M0_0߮/l.fK-r30(ṽ/6>/ ,,(T,v/ F//Q90./s100WV0u/CC// //A/݋T,/(@0X0P0fS20ł0/^:0 /ߣ#/A0/ 00xs.T0&Nǯ/;Z{^la^jk -H0-ԯtk./8k j; Ư'!b_ .\E.9n-暰X0|&0]<._0 mN/ l3cׯ.,,v j;0 /'.݋0`_/mή'._/8u/"'/Fֆq)8u.xs/v /Ku\sDj`0<&NǮU_lL/L;6/м ?C/:`e:(J/_3 _=?T,许q F/gE/Q.8u/ze/9n9n/{ 0 ˊ>(Q(-oK'0 (/:gIٸ?0qˑ0 0ߣ8uj;/Cd[/= 16>/_fU0_/ V$0 {`0瓯 /3AZb0&2!%U+jD/_/0$ cW/l:g/U0X0Af\Zl3T:g.k /:`e/x0*i@/.S3̯:gI/8u/0l-.l0_/]0P0. //*ׅhFq1_xs/k /r/. %.k /:`.l3-AL50mNz.00T,h/(v֧ުq?0/9n-4/:`eC//&2EԮF/n(C.6>.Dp/Q"~.y8uq/(v/Tm.?/xު.:gɭ6>1/0~&/8u>s0 0:gɭ/ݯT,.eZ/ԯưN./8u.(v_.:/_ł0\(v//ԯ6>v +FC݋¯cW/8unx=ׯG80_v 0gE/r30l056>.=/040c.Nyg0x/mN0T,h/:gɮ508u0.6.\s0nj/kt}^mF/#80.ew?]ބǯ^!Ic 0߶/l3NK0݋/D/,,k :`.ѫy0.Xϯ\8/ߣ#_1֌̮8u/S3-zǯ՚Y0//:gɯqj;(-8u/ł/\J/*// /QQ6>nꯞ[n0-}\0/Z~]000.a^/z.;0aD- ._0r 0H0D.mί/C^4,,/S3̭׾//.a/E.0a/ٙ0D ū0(@0~z0c/o&0nj0ҵ0KUDmN0l'0xsaޯ./?^/Dl38/^/łoc%0_0P=0K/20l3.ïTl3Α05/3 njH\Q8u/?5ŰX3.FJ_ְ87_TTl3/ˊ/1SKv:gI.0: .+0!/lD.t0J#ٯ_0K0"~R:0/8u?0a^M%>0ï/80/~&0@J0_QA. 0C//Ic q/h0瓰$0/.(v Ư%U7/mN/X_1D- F.a/0tyl40D,S3L/:`寑`ˑ2"7{(ު0H0v /{/MsJSnj/ /=/n.EԮ(-tE.0/0 o/6./[ު\8u9n- ..62{0B0a0R:>(0 F/?S3L0QA/ )0X/h¯mN/c݋/Z0)00t5/B~ l֧S|:̃łQA/MK0pQ9/PF0/xsb#I+:0*ٙ/S3/ˑ ԕ̃mN/l3-Q 0400t|"00:gI/Eے/8u//q0ٲ00߮l3ˑ0mNz0 F.ߣ#/t. /"./D/֧.8u/ٙAfC0S3L//k ˊ՚<),!0C/Rhk0?/E8g{0O@/߭'+ (#8"~/n0Р/-0h0ު0 %R0-G/^nF*0/S3/QA/D(o&./e:g.(0= 0l,{W4xQ//./l- A,/QAT,h+0/8u.Eے/xs0ԯ*0Q0o0D0-H0/گ-80/T,h\/Gfۯ8s.U6>.=".H/ ;sC208u-M/10+8,&K⨰8uk n.%U/:0o0k -( :X(.k /)/V$lB+0ˑ0*~R0C/k /5/5/ٙR:/݋/M/m/D-%0Dyl4\.8. /8.9n-_/3~00WV0wn09nU/k 0l320/ł F_n/ћO䡯Ic T,.;0w/'mo/yYa0.j//A$\}'o&/:gI-0F1'}/LN`0x0߭~&0 //Z/6(v-H*/_Xů^//. "AF饯ߣ.E >0!/T5$0]o&/C=.Xm/e/R:/:gɮ/k .ު*o06 0P%0="0֧.M/:/.T,/O@/nG:0&NG F0Zzl3-+u>(//w/ /%U:gI~&0Y006>0/T/[k {.6>./f/--/ڭ(v&K0o/:`/t믫 0(@Zv -[Q/УAބ40Z/ DF Faߣ6.H/x087f/ L/k .0ï F//hwU03OR0j/(8u.fA/eZ0eZ\܂6 050E+/\/#̃=_ 8mήG/D$\01S/SK_/njy1"0 #0G8ٙnj/=&0g0߶/0j;0Zz0p\A06c?!.k k {^l0yl4$0ĥ/?/FJ>(6.i[cׯ/*o06%8u//_3wA/e0î*9xs/e06/ZH0850⨰2,.ބ0uu:g,L0Mد_10@J0.00 e00w9n-t Ư+_/8u.T,h/}0:gI0 C06- 0a/="nj#10C0nj L/9n-S0./}@J00Xh$5.'.ߣ#0'v0C0l3,"'/ł/a^/1)0nj/.Ny@ʯ `ͯ{^l01ST.'}/x/*ݤ0ߣ/OC/Eے//:gID0+ e0+/l,S3̯ /T,h=;/3H0(v-Db/*0/C ]+@:`e.c.l/.l0l,мl-݋&NG,/EԮ.40L:0mN/-08u8u%U+06/\/:/{0:gI0+/{^l/'}/mή.دU/R0}/!1 08/9n-/ /ڮ9n/C/DY/m-nj`ͯ;҃="/^m.w0h/Q/[Q$/QA"h]w# _-:`.=߯yl//q/ 0/.ѯl3ߣ/*ai0t/̘/د2_1/݋./L/6>l3R:/?!A*1}0g  /-Te70\/j.{-&d04/=/+0m08u֧.KUD01 xٙ/j;h®yl4eX0-^/ڮD/cWx/Ԯ=".G/..Xϯl8/_/g~90ĥ50(.S6k tnQA.8ux/k /ү0(v/!`0+5"~./8//'. r</Z`ͯ ԕ0Wb0r0x0/./120ު/mήV 0 9n- Xv0՚0?.o&ĥ50Z̮<6 X) 9n-C/'x/*U@J/qU] //}[80 /ު/xs[QDpXV/D-/x/ٙ\ xs/o0mίpi0ԭ9n- 9n.0ު/.cԮk /v /\/p00?08uD/5ҵ<)#8'(vMKQA/=//-HC5.j8!⭣F"'0Z\錰/u&0Z8/6> VW}^8u %lM|ݯ"0$_lfiK0EԮ0zePT/.a/C c׮r30fLN0_/cW:gɬ 0w0݋.Dta鮎wncWD/3/0/g..a/./%b#8u-暯Jկ<.мx//D.5.Gf0a/Y&0p\A/X/(Z/ %--;NG毠ԯ\F10R:0/ %/?0G0Xv0xAL50n/m/F/T,h/6>.D/ήį:gInj.R:0/HQ/Qԭ5.,,0R:/nj.C/N0E0q/;҃0//+)Y&/,(&NG.*/8u95ޯ^/r3:g-E@/j({^l:`e,/uC'Gc.&NG."') ֧ҵl/ڮa]RT,U"0]DٙOd̃=/C /c?[Q09nDުwA-0t~REԮ /:g..׾70ϯyl/gEj//Zدq+k 8ylD.:g-D/0N0000Zz`M>¯r36JS3̯km0$ Ta/.D'⨯ު/c?/+:b/:gɭ )87hBF1.VWo0ˑgM/t뮥N-Hìм2,v/w/xs/:0l3/8u7\.o&/j/!/.c0-H/G80>0/X/r/C=".:gIo&0E0l3j;/-/EԮXł/"/u\0X(/.T/{^l0%y/^ 0a_/xs_0/:gɬ.. /|B0 0QA/Ԯ`i:5E//D\ C/y%H1կmNnj 00NݰSQ6 0 //S3.j;k /gEj0:gɮ (``/"_/CqCׇ/00Xv0HïT,h/נD+ٲ/806.ˊV$08u?/^0C0"~//0a^//C.0Y0.g0 ĮR:Eh//%/(@/QR(0R:cׯ (.!b0\C?08u!0-_,D0nj//;'0t]<.lߣ-:gI.nDEp/ "Q/f/ŞQ/k*/ai0:`e/m .{iˑUS3L!`0X:{0 .ߣQ //^/k 0gEj0$0ì00G/]B0A/+/2//Sl0?/կˑl3.a0EԮNb#6k0L0j=W/p.?!-/0="ab5_1./A8uٙ.v /(@,k .-0oc%^0J.fS/ުxR:暯q//̃=0g0ׅh0*o/Rډ0 n/vx0?/Wگů?/Z9n/A/D/߯ze/x/(@j/دބ DhBJկ&2r3/r/*QA:gI-<):.aq..a0v0nj .4d6iQ0[/ˊ!/rQaEY/[8]C s/.8U/cpmN.Nyg/'/.l%U+.FJ0~/$\/\C?0r/$ QAL50Zz/EԮѮ n-8u9n-.p/0l+x/i@0 //D/mN]04,&208PN600*08.p10.a'0K0HܯV/ G5S3L"hB/S3L/֧ބJ#Y:D0ˑ$\/݋x06>/(-_mN/k/"x n^0v/T,h//D-0T8u8鰤_:g/mo&0t|Hѯm/S3LM/Dp/נ/[Q/xs/Z/!0mN/ į0WV0x$\0\s/6>0//sJ0 el3.n. /j/0WV0%0t/%/Cw<0/87/ZH0A=~\.V$$\/T,h.FJ߬ D/GT,/mήAY0P4Gf@#/P/8l,l3./ Fi⏰X0Te/l+/n0/Z{#10X4j./xs;.a,I0_.6F0(-./`Ml,FJ/ m0_0/~&/mުO//1sO/߶.᯴/{ D/8/o&/[Q0D./T,h-)K00_0X/ JUQk/ߣ^X/S3/"l*#/^0ϯDۯ[QΑ 0v Ax/k/ު/h$0nj hmN՚8u/{^l|Y0,,<߯ /k /- /8uM/~&l/9n-/S3L0L1>B0b]JP0~0+/ ^! W=0)E0[nW4䯠T0Я@0 /&NGE./6>./a/R:00k 9n-/{4ބ (/zeP/100k -/:gI/&/K!/ZLh¯Txs0./~&0?</mή|.k /ˑ/I*=09n/oc00 0jy//~R?M0 F[zeP~&>0 .0g 0:gI/(@/./*$0a//:gI-GJ0+0̃N0D0H0$0 /ZEԮ.C %0oD0#8a:g. 5. /wHܮE//{^lp\a8 /H*08u/50*ݤ0Hѯ\C?YheC*.կo/ڮQ/î8//ZhQ0|)9Kw0)90/#1/`ͮ/?//<;00l/rQ/C 0%Z/9n-g~90'0՚3="0j/(v-QAO)9qJU e0M08/֧Z. yZfS2/X/hwU0 iA/g0)H!/o&0yl4/|'03/!y080:ˊ!/6g5E/r0 10_\mN.?)//%0\s(.x/,ٙ/-Ȱ8u:`e/ZQˊ!A0ylկ/$.p0/C 0/ɰ./j;m/D.g/&d0/0 /뷮u}0˯kG!f'nj.K/oM .hB/.3ȯ,?/wEԮ+\0V 0נ!⯬:040Z.(09n-9n[-0S/m/X/8/QAu/d/t|/"0wڢW"PF1ׇ4Fڰ.˰9.z/n/"r0h0j0r0@ʯ:i!0"~~0۴{/yi2 ):<+F0MR߶/Cs>s0QAߣ0@/}E1N0nj 0 / /x~ү(/دh$X.>/h$ɰ8uQۮ)"nʯ1ӯ/(v./U^ӯqҦ1ˊ!p-)#/í~&$./Ic ݋.8P0 /܂0r0!0+*N\s/;˟/+[T}^/ZL/M/Hh0[-0?!.N6w0e0...O*zE0.=CfLΰ.,O Pb/O䡯]/>ԯn/A/C /j.}ȝQ9/N|c׮a/2,/~ү'&dٲ-%ݰ͆R:0p.Kٰkǯe0֧+/*UO/r3QA/ś0㯉ȝ00{/-H/"F.8.:{0r/9n-/ 0Aa010nj. 00_30\@J/0;˟/V="ˑr(0?/qH<ު/"Q9/o&/Cxs\|?!.T T G80!bD'Uqo*֯\s:gI,+/7 Wr3!b* {/*o.k Cw7/S0A/ -g 린 FͯD,T,. FQ@毲/o᯿T/j0暰/2,A.FJ0_gb0d[00/|&/y3e0//8/M˯p/U/l+/-sO$\/c/0AF0/1/Y&~0y5.Ӯ{;4䮹1/E0 ƭ/s0I*=/8u/*0U'G/l 0$0~I0^0yN/ .>vX/м)D/0fSp/Fd D>ۆz/^5w:`/rQF/G._0-d&0d0/{^/fLN-í/(g0xs.q/CwK .lM0 %..oc/W+ tK/8-O ƯH0D.6l3v0t/\s9n/ %R 1rd-/\0ڻ=ffc.Q0a+_:g,/6|B/"//#T0&NG/ѯj.ׇ䐗NE0*U0ߣ00?ͯy0VL@ʭr򂰂|'ԅ0O//]/{ /+|__DZ/=WfQgG5eZ/ I0?]0| 4/CXQA0/)/WT8.:0P0Di-/0_@ /l*0ŞQ0ۊ0!0Nf0K/ {.N6h®zGHܮg0`9=>VM00 {*0 FGf@ܭ-_1:gI*ݤ1EԮś To.h_6 0"Ɨ/߯/D!/ F/ì0aE.-UʱNAL5v0Hy/)N80k -{90ǯ-.Ub/&Nǯ-0_/P/[0߮&NG/5E MAƢY0 N0W[УTm0݋-U.:g,yl+EԮ.6>d[0TAf/a.S3.yl.*o P0S"/Y&-/A-zeЭGf X0G/T/R/__ĥ5Ȱ: 4/6 N 0>(/e/H+0H*0 ev0﩯ˑ0.c./ZL/,,/) 0;Y0gEj̃=8/L/0_k t/H0F10G/k -/ZL0w/Zz/'-/8/3\00q0K0{^0O䡯ad.0!b / 0N0SAE.0/qU]0.f/..z^5w/ . -Dp//WZ/|W/?)vR 0ծmέYl/BwٙCq~w0 /OV/ %.ϧ`0ϳ/[Q0;2*0_c.& J./:g/8uc𣲼w8utYՎ/V 0|&/߶Eے.m$D%[0\//ڮҝ/j{ _30v -Ȯq/ۯ!10(c?DpدD NM˯k E0賖3NYMW\v -08uI*=/*0!./\Iҵ)/ ~0 Я^0R::`e.zGfI*.j+DpX0"&t0/8u/EM$\m.O!/k/-q'J#ٯį\I:`.nxs,/j/1)0/3YMW0` Q(D0q,%U+~&/]T.=ׯaze/.c .]0_-:0/O/_1..{i֧ï: (o//ܮUz %/ĥ50x//ǭ/]0xV y6l/q.E/ \/T.Q믇ѯwn0-/`M磯t /F1]u*08u3Ӯ8uS3̮.㯻\s.&N//DaiQ \|08u. ^|ɦ/k;R[t/D0m.S/-H0A. .?!^5/{i/8.:\J/Qk<)0zGˑ/:`e/:gIQ-v~0 nj /=/i/.F/XvT,说rGfs//E/.:`寞4M>0"~^nF0/g "0k/ɰvrj"0a80|@ѯ{ 0:`/'m-="/8uX/|Y'0:gI/QA0]+0{^/j0(A/y5/+0l3/ҵ/8u.~0,/Q_ :gI-u//O/Cw<0|ɦ/a^/U/ˊD.G5k //)AF/DZ/~0m0ɿ/î.^5w//`ͯ8u˰..$0l?(v-)/+qU]0= A0L/30mή~g0 ƮUpB0u\0-:/nj/)90fLήQoOدAf/(v/:`nj7X0|/qU/R{Њ/{;0/ٙKUD0{//c//;Яwc/X]8sa*0;!)~&///n߮-_@ !y_69n9n./08u.xQA8u/b/0D 0//+0]40T0/ު.z0 bw0="0D PY/Ax/#s0i/a^-j;-0/x%U/:g,^ 0J/D/-b/Q/l/6m8/ٰﯧSMR:_0B~ :g../]/`M`Sk./yl4.&/&/.ˑ/jr'Gc/z)KEI~/ބ.B~ ^Aż^v/`ҜOh/!b,kx0/!/.LQA0QAqU.|WMˮuC0WVk/<00n- /I0"/ .(,ׅh{.qNyxO0p0Sl&j\A/)/R:0/=--fS/n﩮3Ȯa^00H*/rY }/B~ l ,@ʯ<6>CаW[!0-scE./gt{ "q.*/*ڻ{S3̮ #ԯ\J///Cq.v0g0/Z+q0W"P0vH 0t |Y1S30ު/87hB5@ʮ;҃0/30qH0?s06﩯\0߬-3T-F0L/Fʮ"~.!0a2CM(v9n-j;/0 Ư ?!0WP>("/6:gɮX+ҵk/k .K\/Af/EԮ/~&/ Į//xs._A.g0 (/ {஼.|Bm8/Z̮ʎ*j;0vH0 0hO0 .%B0n-/ F`M.خ|'݋-&Nǯ:A0/5G0\|0/A.м-0nj ]u m 0[8ˊ!j;h믽Hɪ0\C?~z>O7 W"'xs/R)/n10/D,"a/@0N/$0ma0D:/|ٯmLBݯ %/`9׾/_10 F.30U0M/<; %ү+..\0S3.1ӯt+q-&NGn//(Dܯ,,/I*=.01S.k 0OH0+I0;҃/_T0/K0q/l+T,h../|W0,.c/G]05H20o/MA0*ai.Im/'0W֯X/.fL//1#1/ Wr00WV/Z5EkʰPn߯< /0|'0 /_1X/ `M.|/}'ʯuܯt|/(vZh /I;PO@/uuV0N#0w^fS7{ `ͮt0H/l3N0ު6z/5/mN.DpXQk/ 02$m`./N0Q9''.+/m/s.y0 /6 m8/ڭr3݋' 0Z/) /ҝH=lf>s/t{ذ %k .70(/_.CqfD}"iQAˊ!4'Q0E/X/Pb0֓0/)0eRFZ}0f0I0@S/!]k_3^d010W©/߯P/20n-0+/Z///ߣ#/[/p#/c.ߣ#0$,^5/Sd01S./o&.90{h0100C.l}/ /v/0g 0p\/PYޝq/ڮK۴EԮ.V//DQ/$/ߣ#a/F/=WPݽ(`ͯqU]0 (v,ŞQ/՚g0 %үG80ZH/.l/okǯ6>֧/Z/0.a*U(@0 IQxTΙ[QL(@ '𢯅"/n-}Dpد/8i0Tcp0D/˸\00X/?Cy/נ0njw/0L/ /r0U/:`e-:0\s/q0-ۯ>(/S3̮F05/M-'wn/(v-U/.`ͯ3n01/mު0|ɦ- 0EԮ5.7ѯv //A\q0l @5M^/Ék 870ު暯ׇ0-.6.c/Zs랯oc/'ˊ/ҵ/[z7//=0D0"'deZ)9/zqu\p#r/gE.Mq-/U0}1n} 0%U+ߣgG]b) 0Y/0 kmʏ-<Ļ/xs9~gL\8iu.̘ 0u/Ŵ/qWԯ.lު^Ǜ0r((0j/ܭ) /?M/y0<0 50wޮXoG0?8 %-o&.l?נ09n-.c/_ـ/00).rł2}-/ -(v.ݨ/0̂/JS08/Y.ުZLyK0֓0鬲/)>BvHCw<009n-/(/v=nj-I0$#@3/g0|ɦ.$*/֓/6; ߫T/".5E.//aE0#00u/7p`#/sO/xC :gI/;sʯ'}-b50QmP= Ӯ+/j;⨯'//(./"-^5w/x./^5w/),0x/ipq0g/N70*U0X/ ݋=kG#6 '.60u.J|Y+//!O yŧ v/Ϊ/2\|B\^J\(/QxsN:X㱯)/t/X /eeZR/c/ t/aiś/#]x)C>m/p/FR{00.Sl0 %RPY/80o&.SVXE̯]V0͵(//ˑ//g//솰c-ۯ!l0/?!/m._0 0{ ֌L_{uP?.ZLsc+0vV870}0OЯ&Q0vvL/ߍ'm0^G0Xu ad.0SK 0I0&K/ q0 =0&/LN.LgtAfGjԯvT6J D~<7L.|®zeP/(v.C.A/9𻯤_/i7Jծ 0 gC0|n0i0q/wA-0/00Gf/+/l3/<Ļ/6J 0x/D0Yh0 (0 0"00X?XX0'- %ìjT&˯:`-#T5/8i/30p0 ԕ0c/_1.87/aQA0XzeЯk '9_/נnj0&QA- I4JSYzeP.[%/?0q8/]u*09n-/e/]T}/j/="A/N"~/.qȯkmC 0O0/}/80vg/h)p\,S3̮Kw/5/kǯuU0/\b0ݩ08#wA/Et:gɮ.㮝AFJկaR:zW8uU6> ^!Q./V 08i-H/#00?&0S3L,..,&0x>000S3L-zï/֧/|&0R:0ބ/\J00m/:gI. e0gA/fLή{^-ٙ/\s{^l/=.!/T- 0/t0]/w7/Z.~z/[7E/fLNz/x+.AL5W©㒧/.sϯ.ze.C/ .0NX0}?!./l!/ N/MG|0/^/oK0fު.ì'.0hB/Te/+x PٯʰS/.0k n 0L v/ހ0:gI,!1I30=".G毁v wڢ\J/.'Gc(D<^O'0 /Ƌ6/g{/PF /"oGf"B 8u/U^ӯv 3{y{. ԕ/3ȯÉ+/龮q%\.`\C/{0h/x0c0m80I/{i) 0+/I20|0/篨C񮞬.ϳ1.%0LG5P /.ai1 fU!1N c.P0DR_0i⏰.8u-/ޝ00/ˑ/0?6?!vq/tt(y//֓0/T(0Ksϯ;2,2D-.F10T,hOR0>0ծ/:4>PY2,*.O:`e./}^h®7C&/m"ω:gI ?N.0.C/]4eva90-H0,ؘ/QA/EԮn./5/="rY0冷0V$/ު.>($*$00x6/l3U_30./2. / I6'RZH/|@/Ɨ?!..LN`/znj,njiv zeЮ0L į)䈰f/50Q9/@o/0[/򼥮){0.֓ 0="/A.&/R .G8/7SK/:`e.!/06>0=-\40) 0D,Nygv/\r/՚I*/ّ/>/Rh// 304/>į(/S3L-2T̃=R %%0U-@쎯x|.8u,c/[Q/-0#//K'0hEb-7Rډ/-[.E/ .uu0?!.Z/Y&0< G8/.il3/k ϳ/݋g{/l3+u/_10AƮo/*/ F/="5)-ȯcW!fS2Ε_w#/ /\J/xsZ/{^l//njTms10-?.U/800J0݋-/AƮVO'/8u*/1_/u0i/s/nx/+0 gX_;՚9n-/0?0xj\fU '.E/:gɭC-/eo|;/gD+Uve/rY Z/0,lm=uܯ°!bfS/Y᯸q^/5ů?M ƭj~#0600.0֌̯x/l3.uL0$\/uV/﩮5ŮZ/'<0j1U0<0Ƣ0B0:gI.ȯ/ /j0火/<.Щ0!.䊰Q9/e!GOi?!. 20w/lM/://.0^20 Te|aޯE0W/QA/j"./ى0/eO/mo/p\.i (@/ .A=01/_0Pv30uM T/`#0o/b͐x.>(ǛA/Ql+0) .ϧ`/խtk/9mNr0wA-00(ݯAx0LN`0#T0{^/~0.@K/-|'0&d0;҃//0D/*0$#@0/P0Zz0\J0S/(-P=K0YMׯE.L/)$Km 'G_h.'|mέoc%07/.X/t 0@J/ǭ/"/7 /nU^Ӱ*:gI/î*o/r0}g{87/=݋/`M0k /Dk /㱯lZhˑ 0:gIj;mΰ_{{0mN06/="0/87E. 6>w0nS/͆^d0,C=/:;N0(1Nݯ0WV-Bv0/LNN(Ҵo.0H60~,o0_00ϯ$ .~0)0D'0F1}\00$/қpRiW05Vح0D>1^53/#Ԯn,M./%2Q0 Lc0 ƬS/(v Q0}/,\0"0)rHlU/ɯ?MF@;wͯB1S3,ư˸0/i.,R~xf.0ܓ /0qWR0_-G6I05O/f0暯js50}0*0 ,0d0?Qe0>jL0EC/Z/Q00ޡK0Z0H* T $#&NG0* 130~ѫ0W©/%)f:`e/+q8Pa/<0C>m/-/SU~1/s1/ު.!od_3/&-Hcް_@/(0EԮ-֓/7 ׮& Ē/R[0z/``>M.U^SU_@/tS%7.00.0.ۼ/r0#0KUD0p0L}0M'P.˼0 /\ڰ870?Q0`Ҝ/' bwŴ.10ٙ/(//z+s0ai. /g ԕ_,$*/j/.p?-.{/xs.E.S%DB{i ,6:`n/MAAL-0=(@ w/i/K[@F00'/cj {`-0ۆ0N]0i/z/€CI/ł//{ 0ݩg=gڝ0D.9pY(0i?r0ͳ40t.@gIv/)m01P.v/ H0yւ/-b/3H0}/0-r0F0mD0A/ŧ :0}[/RfXWѤ,/給0qW/liP *t.ynPR//pADK' )G_X3/EB/u-x?l.K/009:ؐ-^AM0G ɡ0p /R&fՒDt{د/R1x 1īEE0tRx0WJI00-0ӷ̿0$$z.00F0+$+/^^ٯ؋0n>0f{/bgp/"HѮE p]-b$fR//4@ѤDpX0ԅ/rB_0P׮0 -:`嬿Lc0*/jG 0̘0S//j?0u/QS/S/P>P/6qᮨ/)˿ #/km/-6([Q0ѯ0ew/T,/4/bm0_ـ.h0Y0)GׯuH-0k ,a/kK0!50@/Qo&.mm0F0S4_/m,I/@/$\I/09 c 00_t/VE^YǙE*/(-,ek=/h*/0`0=冷>0ʇ/A(D.C /9/">W3a. [yʯng0s@+?(]-.S=0=:f]0A}°-m/D a累0+/:60:b r0񯋺U`/1_/C/B/L,MR˃u08$/;ʳ0(0Μ0м//rO/((0 QŰ77/ưM1~.pIG0 x//&/ìP0m8.ݩ{0`/50 G]C0w70l*6p.se[0G0'~/X2nB0jC"/R4p0?$/0_0 .즂/_/TDab0لD0赯-/S.#0/fد10ol//e40;l.ڂ􌯴 l//8B0}00.W!/]cL.'/Y]!2/b//C04050T0>+gEsV/ҵ.ut뭞-(ݮjd/J0].7x а: *h0mά(>0ۮ2-00/?ϯT5$/.//U0v-fӞ40O;j/<(ڳ/90Elp [C/Ŭj$,Q/SY' -;0ìRVAE?"6P/bKtbVރ/l,i/t://i20.RB(/t.=W0󼉰Z/F.r/뗰/B/7v'hDzFℰLS\O$/ܯ.,Ϯ 3Qk@0&0 c+/,0L/6SK1ůFl w/AL5a`0|PF ?.-% 0Z®/N5`0&/W*ސ2Eil0 .k4n`9'/o.<%堰W0=_/(@`A˰l0'02Pݡ0Fg/淶hZT,b-0ì0W[/] 4ȯvohH\/_2J}ڰ~64 F/m0h/tBS͸$#(Ls. 5.090A.?b03z0E10%/(N8ϯ/DLAb02a/ $Z4/$l҉0t~/?M0v/o*V/^/~q-l!f.=\0* PWaJ#Y.0H0DݔS/x<[.R@ 0$-/W0 0y#0O/!u&00 00/80.0.YCήDK 00/T/A0@SLj0F4/:`e.S0v00Fg0$0mѓ/0/y/)BW0:{5//(/2;0Pt01Z),0hJ$ÙR̼ IZЯai勰_3.rJ0V]/H0PɯQ-+beFl߶/|b0!/0b0U/-/i.iyF. )0B0%& 2 /l"0.0,kN1"90L0I1f09<0f0dG.;0/MR1-wڢ704 0F/0i/0D1-kݮh0㯷 4/؃X?0/Ɨm /<0}/J;/\/U40iۯmN,N녯tLԯY/x0D{ Y/1/(0Gs#θs/-jk4ɌLï龯?q/6S/Xѯ+2/J\Tn/׵/;jMR0>]0klTPƯP,0S9~Y/0jD/s/c(0o00 ./^f0l/vx/4/10/^.m֯0Ɏ0c/賖/ 40f0Lf~q0k00MHh0Z-ȝ/#J[/R 0]]{gᯔ2쯗a.oM Ax&0Rq@@/uzf<009/\n+$@Vǂ0x/$0L/8.0r3(/Sӥ.ng{05H20M0.s랮֒0`1WSW/*/-(0/ai/A/rA0 /QA*0^/}/Cq.i0OE@0VWot .Z/6׮~/M}?!/9U/wN///~0ͯ4Xt0E|:W0410//@/M1#ꮫήU/H`060i60!'04L6>B/$0 .b/) ^Я`D0N.0)[X F8Oj0 /r//*@/X$(gK0dX>0/%5>Ax:8Ax/c6z T\{0o|//#0,,. 0Z.(0;j 0,~.Qر// 0cS0`|*90𿯱/I0ʮg0A+0C/0/ڬ,\g{. l<0E.ȯĢ/9b\eM{ְ.a \A`x ./6D.$///u~1s0S/@J]f짯m0wq@Ϊq.HˀW޼/0x-'/D0(z/OJŊ/JD/7010կE/ٰoT5z`X/Ue*D"0|' /#0W[/E _ـ?//Uvrh)0ރ0'0I+_I/Ҝ/̱0Up7/ZO/0S04/Ǜ0|.]E/MK5Ŭ𕆰"e=eE0|0Qu1<ɏ5?0t/1/`sOxC0wy/R/ۂ0g0CD0/x0t0*y0;^HF0.FS.[mo//000d(=&/I40d/Jg0K0b60,~1 2d6.:P Qr/H\ O/LV0./a0/t/B"믳G.?!.+$ġ/as4h.XK0}/ͥ.4r=U/O/,/ɭ~A0%!/ 0K0ku.-cS$6_/ZF.5/BF=I=0/0Dٺ00yc\0 >B]> //ǐ/w-01P/)J604 X.( 0!b.`Mj?/#/ -&>/.('P/s 08/_G0V)ٱ/~P/F ~$p I="0k=/k;Ү[0k./\۰3[/$W/-0l,0G6-LEio0:/Nn&.{ 0Z̭%09S0]c/3P_0t ..(@/>:`e-װ/8s /s0 09/h0(خ-ӌ.b0&yL/L0x0k0Ig//30V)0 -U.0 k34."&t%.%ɯ!G#LV0.p1z{q/AF.\C?.h!-L/J(#/:gɯ*0|W.x.\H2?0uM/S05?v/5 5p,8lկMK/b͐V)4/ҵ.y5VWo./&2/O];/V0;ʰ@./'.A0.zW0賖.$e0aU0h00c!0Q0dQL簹 07 ׮t:`"0\/{.fS/^::`мgC0PƯ`aj9// ;GQ-r6AN鬲/׎$ '(Ur0 "/'Gccҵ-,/P~Үj8u/0Jޯ(I/v .0_xsu/)!b/zn 0nC0/H1!0p/0[)0</F-qNIc =060d0x/eE0QbTe!00uX0b${/20F=-00B0Xo/q0̏/?/Cw.p#0i.%/C$\/pɖl/O yBϯdh/c/ׇ0D@ :`eHh 0$v0a$4,//k݃/(y/ASi0.E/@s0<0ۯQA,0f0o-vvL?߬K/n/6>ܯ׎E<|yZ/..B0K/ʮ%%//'/ʮE0uC/{g>/l}0 0T0)BO03H/K/oQI7:0`<4.j{t/,/PF/qUݮư=(X#/ Y/.7E 0+@p0m_u/jܯ<)/Dk䍛/bT|=e///Z.츯~/wy0V^-P⑯40-5./H0۲+0u+L030'0 Û].' .N. 0xG7h/V/[0_hN0j40iFK0 '/_00AP0Dit.HF/"10.nj cI/̃=-0ESc/wJ10#R1A@0700H/Vkа62S6VAC20-0/p& 0-.K03.@r/oFMK0sJנ/i0Ic/00:`-i70 0H0/e.0Q.yl40@/J\/c6B]y0H///z20On0zG+iʫ:/ yǰv k3:+0݋.}80d ۰/n/0A0u.p]-em/1KV/u}0D.-F/xDWP2.`9_ԯπ 10fկ. I^xt0?/ϧ- /ta+-+0CX//./?/:b.0M0$*$/0/0o*0/l/3/I劰>0d(:0c.H'e/OMx/F0/Q n.S0a=i{/㰞k0J/]/7/_˸\0 #z/;1(~E:gIh堰q/r/ș"ǰ0?QAPٮ*vߠ;Q/=_ ϯEwπ hP .\0_8;0{0D!0뷮d Vr/ƯM/Ѱb&_1/sd2:Qud8u∯w*篬@|:nZ1"SЅCӟ/)K?ޯqٯqf/p/t.8u10jB6彮?ׯ% d/j0 Ze0 'A-&00 4w0&0W,0/e vb0/3~000c/k nvics/ mN0m/l/60hN?087.Ic 0,!/2k +0ڵ )6/-.0?0M.t:+010/_ 0q3//g0/!/C -a/n1 02T0/֧. 0/=.=.²Zx/T!_]!G1=|@Ģ'QҮLgED-A/xုůY{;/m|i/2M/zza0<0 7/ުP0/㰉M;+0pJ0N05E/./Ÿ/X/x/ э&0<3EE(Kn%rEԮJN3v@, /,,jFF 09E/kO}/8N/5b1/E/KSаYH0t/;)<Ļ/=;/7`rZ0=;6J 䧰˄al$ 0BZ0 h/o,J1n10%/0/l 0Sd.vvį870Z/ /:0gïCh.hg00Q/ήp𐲯%/$*.// /\/&.M1r@0"/0.cқ^/-Xi֧.}#1&Hh0A+/o/P0d uY00@w^.'5I0 0b`ưV,12H,ͯy*㩮// gt!/SE_ɮ 30cIٺ6/_&4//D/ƌR.N+6g,oAR, /2!.J/}#U PcV/ 0 훶 20N/ݯQЯ۳=.O.0/z.Y&0询H0+.LC0 60Y0s/_g/]"MJE/S/&d/nB0=0q_0sc/\ / /x/j ?hڻvrnΗ龮a.O}0}[80[0Z¯0`/NK,[Q._gbj0(}1a 0v 976=eϰlcJ#Y03T"00/h0EԮ+0h/C>/.3+0~/.l0;0:g-D'@uD/k<,%fm8((دDpX|% @TI0ު~R&1G. %/L %E0rI' &%/wͰ5x-:{800i?r0"A}0/Z/0yl4/QAЩ8.P0׼_0?j'qODH0wA-/Xc&S0ˊ!eŒ0P/ >̯$E./n//Bگ'Gc.3#/. Q/xYA/k A]E/l<Ļ' lfr/g{/_0̰7.,H.J{5E,tf ϯjB.sF/c>0./ # EV0w{0_0[<0(i")T3$0گw._.>0N/Y/O*0/(CI.'/7L/_g/.0ar0y)08@#0!Vɍ/r/Uǵ2uSjï)h|/0s/fmV/ܰݨ/I0ۊ/oRn/.`Ҝ.u㲯r[/t #L/_>d 0<.>DL/EԮ-XVưʌ10&T0|0Q/[$0G 0/y/}/ѡگl֟0zׯ3[l.BU0.g0]A/0}//:Ыg}M01) %IrfS.Þ^0T0?//JF0/ cc0ipq.wn%H/0)0w09bu0Q^0ٍ/c0|)M/%B.G~7053UcLU/'?0u/ǙE/p/1^䯕OxЯ(Eӯq,.q;/`#0&}0H.~&-=\) Ʌc 1i0/*E0WTWB~-P0f뭯(H/X.ڲǯ)U%"W/Fk/u^0LC0Ma&@?0-̼c%/X0)?n/0C`/ /m30.C4 /^vϰ dBP=.C,t亯_|zxPݽ.yүǭ .Cܶ/8iJ0;@0/ZLG .F,f.0Yh >@1Zz/߯.8/0.BL.CJ\У|bv诇m,P)ꪔ//޾.# MK,m020rJ0+:04 0L/]/5xůzePB֯6A/U0#/¼7G 87.!SĜy0.7zs+/)`"`]K$/^ר/U X0(D0U.l3]0%0U]6/ʇ]0.ad.a/l)0jq]N}3-e/8uʋή9n0wޭd[1tON]0Z/Gf.0-Ҡ?0<<0K?0x0@/+6.Ư/`خmά*0vv̮30.Ӝ0U/'0 _{0/ג 08ܯ0wn/@ӯު|)M/8?(YTBۯ!\A߭uCL)_(6Ӯ~&6Cx;OkkүXMz90IG0#˅{./G4RB0P0./ ¯,`Vï5[0/-.04/vO/ 0;j 0S0Db/Km0C.0z/k;R5ŭx/v60.5^ܘ0ɓ0;0 0|2/@0850/Cq/鬲/N/Jò/ۯT.U"IcRq/h[) N/~^/?/BO\K/<..Ưcǘ -0s /&W.#%l00]06. x/N-Xe00\_E60`F mϻ/30)BW0;30󰶯Mx0Cϯp0ѫr:>ŞQ0d`.:0:/f0 0TT0I/?0.5̈/\ /^Gm0B.F.200A0H5j+0"0ͤ$RgpQuL<0[T8 I0b00u0p1WD0^wcZJ/+.1i0֮/Ph0Rj/hF֯ޯM0m_Y//|/KFo20K?0yN.u _:K/η0Z3{4 \=/=/+ϳjd-X0r0*0s20̼ 0``~0 hAcO0B00S0 00g/v/Qw0}^/ӫ00N/a$00 0?00(.c_/`0A.;;˟~{ ͵.0/00p:oBLC{;/]/A-EڮWߍf'ίX6/錮}r/ʏoP/3/ Z贂7Cǰl)s랯zE¯/mӠX/z/Xl /M'/O䡮;bw0jX0dy/)/./ ,:Ic//AƮꍯ]4P/lYfw#հ.0:g.~W( c=y/-zePmѓ/Nyg) `/-an/L_06.8u:`e?QA[./1/` /C07sscƮr09./:gI, 0`jo|/q_S|0X6ݷ0 /,d/0ì00 O0Qo50Pw0S9X /ͮL 0ذS֮ج0[."kp0z0d0^f00H0&0T/:xC0L/"-ȯ5 /0<.~02 ӯ)ƯƗm/jܮ7*/Lg0[//8u|Y../}-/i/ap[7/U,/YU'G5jܯy w,t/]E/}`020%@J/c׭賖.4?-=ܯ'*0F1&0?0m;0Q0\~#ŧq0@60/ҥ0/3o/ e0./>"R0E;9/\,cİ)/.l0x /&0K/vJ d_k0 00vB0'oOb0 0$1$!h/E{fPG'0͈/dG/Q-0%_w/J#Y.@鮰 /W9ţ0uHY0^0p 0CW4/B~- /#0gͯ:n#0U_/q\0՗/rE00X𬯐t/zv≰//0m0/+Swv"^?d///Sdgh0j0/F 0L}0a-6/c]0 /S/43'wv/ؐ/} 0T5/D0+@_Xh0m0/&/BN/'ЮQ ;\J#000vG%Rډ/;xC.0RB/ϴ/Wa x/;jf(~篙̰pn\#/ˈɯ&z2 48u+w .K/F[v-g0 ~՞K402DЅ e/s080].<.-;/0LǮ+/QO0/嵅0FB^0 m/Y)K/.,Ϯay-|ˆ0XK /̯ Uȯ0N#0[.+@x֯m/ǯq k3ѤD rsF/߯T,/Q00>]<[rD A'.y/۰u_q 00ǜ//..i0KRd0\0Y/`/ O.|0?na/QALm0J0%0äT/$X]0V,0|.,"ˊ!2.󜯠gZeK/8dyVPٮ,PY0,/ᛯ}ޯ/.MR/ut/qW50PI0Y/ylxs-).*EU,k28/j/TG0q/U0Y//r0$Ù0AVDͯ5w0d/.c?. .n/C0S|b.@S0/0>Vͯ/:08휢/Y0I0$/؈L/'/i/70/u 0)/x.L/,m/b/ '0$T/+"~.?5>0XKp/uyȯ^&QC{[u\X)_7wA:0|]H0+?0 "/pba3//:N+ak.L/ /iJ0}[8)/#{#%~2$/q/_}.:5<4O/c0o,,௅h/ 0\ /2)/Qu/[EOliհ3U0A"8/wQR0r*?ݰJ(-0!˕0Uɩ0Ʉ09n-t6аv(̉0!`g00q,/=W/u\/GfI0_+q. g˰ym /!-z.B0/20a/hF/m--8-/ɰ˰l$0YM0]u.a-?/PF/z/c<1?/}0 V0|@0qZ0|/0/(%|)rj_c0* .;/& uu.tw]0QNIU0/8$z0.4aDL %0Y/&d/w-O/D'p70>V00.030Z/Gm/0נw= B8/*:0FA50&U2$0/Ra0/~z0Zi030N/A.iy-0ADe0E./ԯt/ .3H;J0Af.9/'/02/У0jT/G/\J#/8 (150cpݨ/_u/6/֗lɰfQU.Gf@0".(v }/J#Y/MRP/i~10 W/`Ҝ2,.ު0/$/m/{ -/zV/&K/c/0ml0/<0?!.%U+0/08/% 14/X%0?$/u0m000(/JWS0H0e3WZ.!)~0XT;S*0Es!1/qH/g/깰7 쯉ĵ/Dit.v/-RsW[蹯Sӥq"/̯f,g0pm/0/F/)00ګSbe#/,0\02/8/W/nʯG"95^ә/FY9m_/?/Fv=}rgpF4կ%ۯi00q0ny= i[L/`rְO~0_)]<.scj;k4/ꕯ_@/戏7Vwp/lɰh/40w.0P/gN&/0ȯVW.r0|06@0 ˆC0ZWZ.R:0.=&:0~J,0{/bva0)-ïGg%cXZ09n/t .Eےh///H50D0Q@(D.B/3>#>0c06%.J6)4l0'00u0\ܰC`/0A|0k0m0^//[ʰ;ʳj.pCC/ʾT/S0U/y0I)Q0NIr©կJ $گz]1] ָ,mEےK@//0;f%0`0 0qU.G/0<:խ׼_0e/D.@zѬ/,8?0 h/Xϯ0U0kp:.SU0* Z//6>,A⑻hF.=]/+q./,T5a0l:0ܯ .U3$\.2/K 0k 0/F4U0z/eZ@La2ï+2gtCI0;xj0(v/wA-zK%0r0Nyg./0|0O/BO.'ЯQAƗm00J2/UN#00F`#.&/c>/I/񊺯?."+0B0؆T0ѫ/80-as/ W[Ο/د𕯖ƨ/厇goE7pzF/)毷w 0mp/*Ÿ?0"L0>q0NI/q<0B~/do/Z~30q/ bw.0,I0,&G/м/%pTԯ!įa^j\070 Ձ0v0`m"0#$t|.J0g/ZQ.ήew/b1Pr/]06J 00+/Ђfr/x,ȰDY40u#Ij{ZuïYRBR}Ⲱl/&B0{84M%B/[. 00T@0/yY&0ή$\.e00VWo/ãݯs0/ ćy"̍A"/~ѤEE0\t/O/ 8ԯm3///`0~B0*U0St\C) 0ïXί{_X}(/ˑ.$/>(/6.i[0ζ~A 0A0@՛0XT/0Ȗw@/fr0ҵ-0O0گmojs5>׽YڞC80>ԬqW5/%qUݮƗm/,gf0M0Үu|0T480s/K0nj,lI&կ2E,"2*FFgH k/G&0 40حY/B0?ݮQ66NI/4N/Qk0&a/S ҿ/0#0U0C OL.W)/0/`a/n8{/V /bή/J0êfX0)05,Ѵ/0:/z:X\ub0B0j0|r000'60Z/%믉>ǯ\Ů .gꨮPF/)0%z05V0%H(]X0+6hO0H`H0m/'缯q//6J X2Zi /CV_8;0hJ0`00PY/J/X#<03o8.Q.`X0qIC20̂0̠00t.h$~D9/ G5R:l0%0ٹ//,= ۭ;wS=ï=2uF9ZD08sx:IEVg;055/ju&2jDjVd!0%0%0c0@J].k0/\0;/0i.0&00JQx?0eZ&0R!o{/U*X0WN0/Cٷ700]0/8.:ɮ/ ak0E00 c0 ɭ$?0qUݭ)L//>d02.c#j p. 0<O0Pb/r_0d.<;CL%ʿ. 0Hyޫ;f5É.'{HE0,8. ix@ ^=ǰ0G.] -t0.z]0T.Bw/ r/iU6ȳk;R/'/0)e0/uM.w/`/?.8wt< 0/sD-/ f笮[Q05-/.1l-N0>0h/wί[+>0,o.K02 0ӵ0.l0AF;.qu/^9I/l70鱆/C*@0.'-|. i0t1ح@Ԝ#4M/0$ *|~u0D/A0q0S&/Y9.,ȸ1k/Ev^::/h.E.M/X䰚.GY/bfX/M ,NiK/ R15M0//1J0wz7v00`NK/XEIZ0w/E? /Ŏ00(֯ /u"_Czn&0/~0,8`/)ӰeW#1#0AL5/њ{//؂lҝ/hBl㯮oCzt.bb00!/Py/0~i0;./ EԮN7/_-6zG/07:/F0m0Fm/#0|.ku N? BZzk].o`00#ٶ0-1[0Ϸ/A/G/1K10cODĒ/ EIٰb"&3쯠NK,ﰿ<09pR:0- ^(<6qa/o3/C///9#0Z0ym 0v?U/- 0r0J/,n0k/*eZG-/<З^F(DL(/~;$0ۧ/VF )G+)Oᮗ)!ήĭ[Ek?S#(L @/R6{Њ.1fE0P{00:/0kD~ҭo @ذZT}ծDlFROѯ+j060zJ\T,,sFz00]z.DT0Pҵ ÔCj\հN I-{#0/˵|0.d,' -^/y0/X.貎00˶/`Պ090s/wʯk0)U0௯9 0)0(ٯ$0Cx(//ߦn(\./$ItHI֧]<.GI/QT,.p4x5/ˊL}[Hˮ1P?(R.˷61h.v0݉00u/%3W/. bw0m0Sy'/0՞/('0?02/b5g~Ux2/3{-nY$0afno/a00//v70/8S^/t00_c/r00 .0w0n/Ie/ o-0If. ΰj-H-0ˬ/e10 OnܓRì/>/40F-_/oM0BE<% R1t0rZ1Y/sB0^Y0_0G/# ./ު{7BG?ͭz0~(, /K/t50ڄ *U0J06B00t*/& 0VѯsSS/r-=",6J Iʖ0RhkZqk/!O)̆90XW01lO嫰㭰U ϯmڵ/kl02/0Xl/X/0cG0wᆮ^I]BEr/0©կ0q/Sr/g̰0|.\C/w/.! 0ͮY0/9氼b018/r H+5/@Iq0:oBڶ0n0\|YS.+.0\0&00^C0a.U0tn0b0&/U/~-qH԰ew/!/'q.0/.EV0q:b/)rhou{IZ>Qm5ˑ/.tT0-.// %үI00Q/d./l$0r(0a20Y0L07./& /,,/Rډ/%*})0k i Y/oq#0E0=]N0'Gc..5/Jd [0eدN.,0(00b-70/+ѬSQ/@"ѯv0P= y/N0WY/.`/y/u/"_C.i00a4/VðUyF/C0w/uyrePp'G/D/*10ÐaޮѰ gK0D*0;O+d/[(00yF0a-m9*I*=.>Oi54/\b0y/DC F ?!V0H7f0ϦOLahgi$${C/(E0-0mXO/E{/\ZRr(ʷ.ϰ(.0{70磯̰ ֯lj/*g0'/ V0dGxsa 0}l S /k/p@0]ݠ/3{ z/ 0P0 48;0e/0/z.}1/(@09{-0M0Md/K/}0P@/ڰS/ƈ0^5w.$0V)/B>~0)0}0n!1 n-0.[2J*0 ۱;i0.o/PG 0/-:fLN.&4QFʭjĘ𦯆h˰̠5Gư{0аe[y<tن/=/i/V'/5ŰȊW-/1.E0l3*0oɰ;0?0ՙ 0E/w>0W+?.ê/,hR0q0[_h03s0o//?0Mn0%5U]/+00=/?Gu/c .Rf0.试ک07sNddz00\@0*M- MЯ)D/0T48$?3$6?~)䈰Q|б6qY/Af_1j///bίHl/y{_02/O}gH毪.00"$/9p|}aխ.cǘ0wn8շҰ37~0*^~XK/.,o-*.w0+į/Ͱ9[娰 QM0F׾7/hNۭ./! .6㛰k ukx0060N/[T0\,.?00K ]00/ﵯ:9j1˯{0:0/MR0/0/.e, ˯LLFT ޻/309/Pߕ/ 0fr/j-jjy0!0/ٹ/;0>/i0'"0M 0 1d0+o6/n0cVf/K/0/DDb>g#9-Ҡg0S0A0-0\/ՑX/30I"/0k[/ .yKH}廰(0wA'0ʯ1G8>dL_ Gt{دԜh+~0jy0/& Mz/2+ү0$/.0T!0EEt030tp0|/vq(m8IF1F1zb4@BF/&o0l;000nP0$/`0ec00կ0+@/=.Y/f짯zc//Jp0t.$-"~6>x0?T/ڄ/Р|.݀^IX ిgCV/-/<,/ 0԰2ǥ/Ԙ.1\.-/-Ϥ0I0i}0s08u./%Oy/-H>/afS2Ax.)z=rd./Ϩӯ1I-e1`ʰ>_V0ER9F1YX0v.?0Ϫ/1 0C0/0hf/uM0YM/:/C/[02"0¸0+ 0b/0 A0!/4 k!j.=_ 0# |0-9c䀯h0H1!i|Bϰ7] B;11Ɂ^ "naM/0g0I?/M/ No^/"`/+=A)0W./pC0P /VlM0]0}/r.0Dit.G6q80. 00L0c0 0Ȃ0/0Y?/q0׾/O0ބ-Kԯ 0Y#!/BaiJ/^ /\H/f~&0,! flACo&/sg0~&--@/  [#b/]1 .=03/V07 s0]][t 08>0*1?MOsIm0$900/u/Qů/ـܯ⮔f:0,\/v/A/0 0'. '0e/r00<0#0+5-2累0G/ 0ͷQo0Z00O灰|/fP].ë-0,=%N0/|/1ӮeȀgQ0:40}ޭC@Ű󞰤/]4U/0Euc.#/Үw0ů/j (طS/ǙEDoq+V>hHހ/g.wu/0k;RncAh0BEQiE0؇C d0P !љ0 00E0@:000x0y/S/yc`0ꝯw1Z0'د/*mzN_/&/amѡ3LR9.ư ./xB0Gm ϰtJүl3+G8X.s:l *90Փj jx 5㰢Yy 氬?vT0n150ٹ+>/r0AP10|0h0K.1PF1Et1&1别0501 0e/%m0ԛ/ͅC71].Gk݃/T1l/ԙ=2q11A l.fc+&///4d/@V1lfYpo1K.0!b/`5?10 %ҮԔ0Ц<0j10, 0S}., %Lo!ls밃:3ΰOz֏Ȱ\ s/V1E|.01#|.3-P00څ0l3ӰM0?M.,䰻14/-0%ܯu*1t1 2dQ1S=0 8ɥ00hBB,'Tn1P-L,80C1 t]0!M40ś/0fo#^0Qۭ0101hw/;.᯽V0Y0͠'缯d//00^01u00BF=0\+/acg'0'/ ,I/E/ 0C-W"P0w_*e0gD~0>_2c°?RɰHFJ/He09..ˑaK0nt0fR4pˑb$0h0m0k[>T>09L0(Hc(1DZ/CM 00 0T/%/9i= :NJj5S0`21, 1s}̰ϰ͆/D/A&b0 /'Վ޵S-.֧7/00it믋(Cb0Q0K0r iᰳ)-/~/50/0zd0/w0tka5eD7^ 1h1J000 1+$0"/RL0V0 M0<1[L0w F0"Ӎ00R 0FUO jJ/4 0fU /ۯ˯')zePi{ 4]JO>/_/(yN/7DU0V\C0Zz@{i// ɓ0L00f/ /lo#0]0.0,!y m0-/}/?/Ů/K00?0){0K$R'Gc050^/w~jT W=0vSϯ ~L?$IguL0fڸ7p30k !.];ʆc!0a8/ ZҽY02ݯ6x؈0Q0F0?.sJcþ0yl400WɍU/0l0 /eȰ?0v Z03aj00/nΗ0/q,1=", 0/F4Ujmu]8L|.{aabVlpOC).t|Į$0qtO06B0BƮA1o9F:C1R0<s䰫 Ư1UA%I0y0\W0z0<<Ļ.0rщgqůǰʻ/n1^j0-Ga0:.0X0~c/깯kp+0000Q/i1rǯRuCM0F0T0a/=uϰ0У?&_gj #/F:44.6"00!2řﰲ/.0$ʮS}S۰Z/W"/ .8u+s0RA1+-$0/PfKWZM/V'ܯ F֔#9p0wVw]Ml˰w/gW_/^?T)7s/8u/k#/nk[/\E0JS/gE4-Dbć#0CtKŰ}/K=0Y040+0%eNӰm90h0eUB0H00IɎ0]E`Y _y{,!u!0&Bw;n/u}0̃-0򼥭#0Q0c/N/ :NXRc/װ-0|c0 ܥk0}.sN\fq//װ30"0-|0qL / 0 /j/5`0mk00SҘI./jr0:1z00^nF_G/I/y߯|0dy/p/'F;h臰}j\Fq03ylڭIER /d0%/VQl.10{_0~XD ΰ2ˊ!/5/#0 19rρ/֓@~0=b/:1d(9oa,!G70z/C0=Ɠ/^ /0ʆ&0 tJV^0U0+<(01M/-H/'}.0dw^/ȕ4 /20jD0//.!20Q0N>K/9H/Gʯ@?y 00BԚ0>(/_#2;0x / y밦氹/Ւ.0YP7 'F/ޞ8ɯ+q诮06D0Un0ǒ/>]YU'G0O006>0%P0b0]0&#02/-i0=Tu0/QRyF4U/UD/SIE.X51r0;0|W0\Nد^\00%)1-S0ks 0c1*%/0 ^.*%>/H104 / %|\ܰ[|̼//z60H[9Mn;=/C0/_ذ/6/#/a8|!0T/D0d0*F0@/ 20O/.j1M0Uݯ/˄0W7G/M0`0ð)..PYӴK9hOJ00K/o|/Fֆ0Dp0E@0onЂ/@e0na/X/(.a/$0Xq0P10l㯎*0;0պd \ɯ󜯧b@T484./@`FY#'İ@/􎰣߰ :H0,<b/ t2/Ck-4/ "W([/!N0a2C^F0̆+1j#05/0"^ׯ0jP11 X0 0He1r1M/݋.N=Ss|0/ OmTV &-0va/wB5ާ 13S/00'C/0/0KA02,04$_=+p0U1rG0Н020C;09s0^/gxv f0x.\10 A0g?悰yj˷p/vUЇ0/X0-Zcuw TA0 0^ٯz|­~2{"3aI0TX06'/ m 07C.-,DCH/V/>ðM^%/NL0?ޯbf0+/(֗ qߛSs0t=-a[tv0A05/$0&}:V~/ 0XRU0/\0ʻX0V0ɪ070=00 Y/Nd0'mNPBp1a/0030 "0U*0T# ӍfGc`/}0o 0ѭ0!0Ur0w0F_g#쉰@KI/2(%0*/vt,qɰ`Sӥ /?T0<(/j-v/fG>0#s0wٶ01)/ 6/g0AFE0b5/ ZGp[0ˑ<600Ƣ0}0O1/ɓ4gR=ȘKy>U0-u//i0Za0Y01[-0G1D9/좚= Ϯ8/LͯnV`+0.Y0m{.qNiS=[Q#X_7Q0ipq/zVڪK'0?/DC0Bł-e$-0ve/ Iu0Y}j/U۫㰢xߡlc/61華k^L10!"0:0d`m5<\|U/|+0 =0+0VVg0u09娰D+ o30V0Kw0̴00R5B*0m 0uu`잯j.gwqͅ0N"05|󮭗00H,F0T.֮۴/l~ʯAѰa/&/贂00կH쮡4΃.3S̚/ I"ذR/{,=2z.x0..h0ޝLΰ[/#./;0Rap0!0L!0,{0s+#j"+H/ݨ/0Uy0;0%F/|atT;51A50c_0G0N﮵ [h姰|)ns ð{mQނxC03/LN`PP} 0TW¯n5誰hB-+OP0z0 ..H 0^_/h0~q.y/1&;0 )0t0=Ɠ0fT0_&ѯo<01έJJ000ZFs/40[0 0Q0a0.?ـܮ5'H0]0/hh//X6/y%7p.|t20H.#/˴t0i[/{//+m^0Z+W/q]0]ev=/C>m/ 5{A5/C]?>/ 0S3Lq:`e/ٯɻ/-:iF/e0Z.:hӝ;0/毁N/rlem|g0[0//"&0@~f08/^O%يꮯz/] 1T10"0J ׮;0|R5ab0Ӕ0DB?!.E/&/Ӗ.b7 W/0bL5D9ᯖ-/&°YT0<40Y0)TMRNOi@/0#.Q/C\Hmw{8?02o;b (NU0@0B06//0a&0DZ/e?80d0V0mX0,׉06%.0/H/gE.ҽ/ 0vr.I3qÓ[z2AҦ/4ﰥ#(̯KuAI QkgŰ]L~/IǚQk죆B 6g++-|=/Ñ W~].x. 1R:0뷭r0}Ȃ.ɳ050d;|8@l?0;v+/00]~/0 0iy:4ꔰg/0c?. !2zٯP0^0́./0r)8 0rFU2Gf&N B|ɦ>/0W<5xE/h_ ,T#0f|-𡰫;/L/V$/]ߔ06E0;/o/l/ .es /E/ %R0[/D.~׵/9/T40.(ae.|0#|^-F10_N/|8ůq=%NƱ. 0t0#ԭ2q0үm/ ʛ0-0@KPm6J x "0 Z'3~Q000%$/A.tߛSd/,"0,'8yl/1!1m1/0,/0C./0f0G*u0[14df3db1zc\1Prpb07q0mKMt0`:0Xܫ+]ba2/#rO0vH])/4ţ%@0J0KsBy>Z00ڳ/.0uC({0` 1'/A0y004=01{7/-700аC0+j.`h0N0klQ0K/'/ 4mV/0]+[츮1u1U/ 2/o1Y0H10/F7`.0QC/Fcǰ떰{Ơ/ %61v.#]//阆1ǰKҰ6 Xʯ#fPLޯ@5?/>#>0M01]/;1>00(1ƙae01X0gBw)d%K/ҩ00-Dۙ0Ȕ900&040DF/F/(|0v >/ڶ09'00 ְ M31Զ0*qrm 0:Vl0H NyZ/ca0F=/cgcӰW!=Dr0xCF&+ !80of1%0/k^.L_2TJ\(/s0Ԑl+0\J#-nVW1ϰݯ /Zg/ڄ /0̃=0 03.>B/ Iu0+/ [0I04M="0ð0T-|0 =0{0+ssʯӮ/00JQʰk Ot///v?U/0ӛK/]/%k̋ w;0q/ E2y*/qNyh0L .>0ޮrLOŞQ.P,0<[Y00|ىP\,tAC#aĥ/il/D0i[0Ra󹯂4 /ѫRډh/7a0/Ga쯙0i0b0ܦW//r0Zʰ0EWL0/9/km/0 1P/"T0B/,_.lm8T+0l d30Ȕ-H-m/b}"itKEy>0i0J0a 0(x0O~00X E0 Ofz0/ 4a\0LM0O䡯njz/ '*/3<)\/<1RsﶯuXj/[ 3&0tӰqİQZϨLv0vݺ0P/0:_x0M..BJ#Y.B0U/T0j> V,.80p%X$X~'/^0H/Yįp0kdK/k0tz.K/05F0_د>_03o0A/\1._/A.d/u.b .읯?-qPqC4.Tm{0%Om0=u0l3J IdX纈0/00eV0^4N*0_/F={/.?0 /l[pXٰR,0o./{0c."/B+!t"԰0%S3̮-eV1OP0}/ 0%I۲󹩰𑞮0K0e*./+U KZY0800T,h/G/vE p?/skYtʰA/O0{/A05錯հMX`9gXّ=!r/^:.]Edmѓ.5O/ b0ݔ8̯0Z~0/ /s]d/Ig00MW0L0/d0K0R~0[@/]/lS<0=~0s/|k/䘰`cs/b&}0CU0>.kݰ~㰥J0>$07]0z./^Yˀp%JPY0*;=G(:(hðvJggj-ٍ0a/Ű7o&ؐs0 氮7΃0KY0 Rv0S//B0$V\/9n-9p2.z6;/0Jꯨ6/Oְ Ά/\v0f 0Sկ0 ʑ\I/ưH>1b1X0\Ag0?/ֆ/kgI0lopq-0ex03"`'0j0$y>0< %(1 D.e/ (F-60P/*}boc Ȱٯǔ/_r0>4䮕0Zu/-寂L/@KI0:Z>X$70=Q/,ɮ0-:20Ȕ/1`԰Nf.A0s"em yOD^j/o/V8ڋ/p(?EYEk/ (/2#t|/8܍/ws30[X"/P0 0 0BǮ:ۯo-ֈeͰҔ./ 0C-ê/a40jz0qEt/ĝޯפd(+! /zg( oMIԯE2N[˷T0#1#r]0Ja0X=-x+0250q/Nw 0H050K&/}b^/AO0Ɨm0|1^ңY/ '0p.xjܯ3S/Ln0a.Ϯ..ϰ__0΂/MWh0jG0s07 1G0L/1 >g*ټ0CЮͳ/g~9򯙼/0^f"  VQocQ0G/./0m 0 }0}0π /!b@gUc0 1k0ߠ'06/[50{01\ jB6 0=V0k0=.]y0hL0rY Y/?s04R/0.5w/Hy08t0k.FG-e@4K41W0>%x0|z/Kٰ\SV0YaPn0"ذeدt<@M/2Ű)G}^}P4Gf&d&R\R6?JA&|-.e/;00b[%.?0R 1Q20̯0s4G0t>/K0x@0\0IM\K1 .4.[x^0r0,dkŰ/D4}Q0G:w\pZ^?Oz[7*W0f/֊tvm-:01U}I7`LV1A/c00/B~ p^@G00]D+091V / 0êy8.fl0P=J#../@W0w0\=Y/1!0b^/޺ڇ0{g/y'sV/_/Y0/^0 0>05w߶/ˑ!/<[0Q9.v [/WUO 0S0gt0ԯ8̰G ޺/Y/&l0b0q'0C1$W/ /)10:070!000q0E080,1V"l/v//_7mye%R:,x[0i$֯tO8շ//QxdO0v® ѯ6~0ZPP::|f//uhϯ;2*KUĮ#0.8 bw0`c.01E/7Gcy/:$02/h0G 3500F0E40s06خQ0. 1[~09<0{01O%0-00 '000$Q0*t/j0Z0J//shK[0&}/0Qnc0=m90¨/^PBc0O/ӰVF믞oI05M0E. /Ӱinĩ</x 6Rn~-8LE/ï/$\.qip? L K02g϶0W%0Eے/.q0:8"0@/3 102R:.t20qy/(M#1T-NyhoM3ҊBh/;k0+0v}0u&x9ݯ+񯠗T.0 =0;UT0aِ00m1 0 0>)01߮s/\hB.cƯ}#tt:m V0b0l^200[/篒o/<0//B00.1>Z1ѫ00"0*ޯ40/lcv0o.)Z¯9?0ʰ~50kx.6 !00s"/00/k4`%O/+1~&.-,9+00p0ؼwC0؍0Z{Z0+.!0/ަ-0/2x0IU|0ir[W02 1XSy9/p.m/CI.𑞯7ï{͎/azۯeA0j0>0qr0SDj/#s0 USpW* ϴ?{0Z/Z8070Z/(0.ů{0ş0;FSo//&u6Ɂ/I,10-/00_30'/L0V1op1KwpԯZOy Yϴp^5 /0.0}nb/0x˰ư()/F¯kp0\ɯ/_u\)-/ck0̃=r YȰ/fMB90d 0k/n00/600Hy0}S0)0U"B3A|H0^nƮ`0&1S0nV0%/0Z/U:0!f'/}- d0l3'װ#//.2g9#0+q/¨i0v~0 ݮ,/Xptΰ@F00u/{6 0_5/ݫʋ0?0u/s0C@ůϯc? 0 0|Q1000S0墯Zz.弴ǒ}] l-hmE>' 4NQ<01Yt4:m:ׯeŒsKQ*|Ke0/10%Z-/0)|0vԯ[x/M0x/@0k0{10t / &00r&1w050 0}];o0jw0}0s0?ͮ%ۯx௫jX00b0/ZAf.F0/Z/*=KkمI&*0ɰ[ΰ1ӭ SUSh]/n]0^0h|/5ct0P0H.n60Fֆ0v°}(/)ϯ T/0:d0\1͹10Q0(8/?/G0d[yL-[sX\/L/-iX1K&1M. ./#1VT쐲-11zl H1B!.d&.B͌/Я/Wq.c`g 1 S@3/>0rR?8u0/<1PCLjp̯KJb.yc/"0w.ڵ0J$e^ܟzV//b(00۰]00006J'0w/淶 b /j0Z007ܛt0,N0Y1[0dR0^0tB1y'1j0*1%1*?O0j0?"0L30X[0]u0㾰0L*߰ǰ0ƘY0ЭƯ凯rd/xǔxYذJ4J°MzU5C0PdO*!b-gD_hL0\F;0#0 0̠/j{͌10I0_t/9c03U(ޯ௮-ݰcZQ0ȗ00v0RؕUx0e0~ņ?7Ql 00c>ڹI20$0g00贂7摰w.00̯A笰Q0cˀ00W9 1e0x0e:10[T.040Ƥ0tzl0O00'U0z4cUz뮛)10SsJY4/r/t'Q%1ந銯Ű_2{R.E/R/(0nGbMmή(o/CO#U.mq>0wUY/&/1[02.b/{/00ei.1=TOp0/Ś0R1a1|OA/TJ0Qla^.Cv S<ce0m Ϝ%0wODrg/sư0[600w0ŧ /ͯ\/ŞѮ;g.Q.fl/_6㯸=$00/;c0k1q0Hx0b/ /./0!0̳lL10\|*sΞ/400]1A0vvohVR֛0(00%6H.d2jH-0/9QZT/~k/{ς0y*A0]9.z.J0030WگEۯt|ˇA00/󯬢w+/ rKz ̃=/5R9D3Ys .&1PItZ/u"/ :=Ztt{دvH08ѫ3/W0)/+p00!b/ۮC1貪0L0^0c0/200!1&0z.ٯU/<,2M%0y:9cS0[Q/+*A0}m0NҒ_0|ήQŰ{3S!00P>Pڰf/k /|&_ /=$b/cƬ\D0fɰ~ Ұ0n1.up$1$0n0,/}0G0/0N/h 1:0~10B0C/\J#/6߮)D/0-0h/g]<(ES0y. (0p0Q0΂ /u;1q,07002/"000мol1Z/^0\06 "4y0ϰ1 ʈ0>'0Z.0EAob *1(\@_2*0IY䱬r1&аS1$0贂{˱&! 2Hfo/191Sf1h0?K¿wM51~0˱r3i1Eے. 0Ē0sưSӥJ/#(L/0ͮ>N}05#/(.P&#ɑB+@0Yd1ӝ/E0w}000ᗳ/|{i$0 R0Z!1W0a9xjܯe0 ,0Aͤ /.Zg;,2 `r%'T.$(|KI⋰^9eqڲǯ0Cv-1{01T/0--͓0P|ׯ8911EB0 *0 E"M0>"00c0vEPy0AQ 1dBܮ.y^.0*0~I){T6E8.0 6 k0^?{D)M0, N/)/I;Z_sR/u~Btx[ 1)䈮 ]00 Y;b04- 0a0of0:/c/2]//S0M0%)0L.Jɽ0ՐW1\1K/nְ0`X0-|11 /0 cطS07`05u0@f/-Uߍ/:0X) fj/s0{Ζ76),gf/$Z700e>./c$1sB@OܰC 9q /#)NFX5knIG/a0ϯ9Yְ~ 0[00 ȰT0f#0}-Z.r0>0qUݭ*)0P0@/v510101Ր1U/鰤0WVDCv09060 l1i1.1X/ :_T@/eUB0Qލ0q^6 1q۰i%/f. 010qUOMɰh|/̶L0/B밨"0r0y" 1MeU4o`07ua並fKְ/8=020j늰 Yܰ&Ȱv 1.<ɏ˲nj0 0:00ZR1%0`h01T1Ź06u0.׏/ X Z0/0Z0{0A00 s1'!1/kD ð00 E0l07D%/D/`0y0ql0b0'0G0o^Q'Q 0ET/q0/ᛛ7ŰQ/ / 2 b;%Yڰ.Ibz#'l؏/VĹaˈb."FȗzMA0m0J'v0[/6!zg|/0{:0ٕ0_603L~s5Lܯ/e&d0`/ ]ػ0711Ry0BJ000n1/01) 1ԗ0T70! 1M0W100K0Ճ/0`0|@/.(D.xO'׍0]H |B/p̰a*2-ΰnH"n^$0ƮE+/O$0h0Ֆ,.x9o }-_q X-y>m0 $.1k 0x 6/\{/ن F5A0f90:ߣ#0 00` 1w0sX10=%ίfR0=&:L~w &)έٯ_2P հ˥0AN0/+,iE(0? .K^0a{a0 0?f07x10-1[?Q&1f/Rq'O01S0>10Z0lj0m2B0_> 10n0@0C0 01V0b3t٠61?ҰJ ).05\ xj/ ky3/) ) p$l6Z N //Z/$oZ3"y3(/imӕ08ڙ0!+/-0ХЯR08=0 1SD\.v0100a5#1A0rdv߮/0!/;0z-00r0/=,007װ(79~0P<)./80 ůy1Y18r.0Cy/#|[Y! -+/y.IM0a*s0 /Hij/Kk0ݝ-<- J,nbZ8 80|V0faA,ϯi0}H0;[u0­040`δ0r0>X0XˆN 00CD-0K1Vɍ.м&$1lϰ!acB/V000M00Fl2ޯ IY[ *10v)+U0)B/H^Ca7/-%`²/'/n{?uFdh00@аPRs@So[j "0Ƌ/繎;1#%ܰ#tTBͰ !GV0JSl03?+0leZ/r1L-N4100/D~J0;0L.1* &Tܯ/- / 0+:O0%0KU0f0h/0K|d00S3L,/֓0J{00(1$0r0(0Bѯ, 01S:華Ȧ&0R̋丰u+f/ .06j0lyϺװhఽ^0iPb0N1N{?0{˚0p,$0X%"a Að-/wD"0f$\0Ԧ#8@#/Iw0,ً0-1[8.R0n`0#b0B@IVQ"اTb0LB-:b01/0vcF/0ߛӯV n0Q0v0r0X2p)1Y0711H0y_1<0yd/30в9U0=#ڰk6b01&0|+0죰kffXŴ-8lU/|b0L R0F/C0u00sQ>K0T/ȰS/'710C0G-qn/=6/Z.?P 0$1Ap/p51ќx0 0SgG010 0B0T,ﯧ0/3.A01}04h00&>O鰭ipV:'CTmd^ꝯX0!*6#$50Ұ4s/|r/M0//R00 1 /G0¡"̯iʰ$<1M41#3uCW~E夯z 040~U@00$(1J70 \F;0}Ěj1  81甆0<1y T +0/)%0T0iƠ.yNBp/ q0yt+1 v0 *[0DӰ=R?:)(Y(ʰqoSvBѰ?򆰊+_ [q1PNBK1dMly1c!41zV,d1//41cװa0׺r0fmp0|Csd1ர=X0s=y1 η0ϛ1w'H0ۇű9#1:t9rAM!. 0 "ɒ)0掱1_1-]0 1㙱 Yi1Ȇ/T/2,.o3 21PٰQW15r~1jQت1Tͻ21/51%n1W10ë1 k1QNCj1۱j 1ıA1ֹ?1ݐ1[£y1ʔjE0##3zl$A|V1A |1̱1D1# 1ݲ1Ҟбg!1П%@0;d8s0m7q80"R01IḎT31d 2/ 2/E1+3_i1s)w1"K+&Q:m 1 1BޱLY1kڏ1;ݱ!2uM2LBL2A1>HgF1aV1B0.152K32̂Q2_*22)},221D1ZA2&#%2+"1X0]0咱2D2]eiZ2"p2̀&2e{o'2;8]2E&!i2~)o<1{07ı81ѱ-h/2arp2dB22|9.2:x2'&2E.ʱd1K41͟L2\-]dl2β2a:岸33Q3d߲,2Gg2 w =2F Q2@R2US2uĂ3s% &3[U3{L3vŲ(2'G4F2!Nnq<2V2RfDzt2۲b33a%3ŎP3-߲g2>ʲ2 hk2)汫 0I2ۭBBd2ٯuO2P-&3'3g 3^+#%3jS/2պ2F5H1 /+h1"y}2Z-2K"d!3/373f 2#2ɔv2/ܱbñf 2[f2 Ҳ|2o2PJF 3Dd93W(,63iy2]/21n.d2<&뱌1q闲<2N[3Q'k:!3@TB3P= 3R 2@²Z`2-_6;1/D N2Sm|2{ o2c۽>23UY237 39m% 3Kkބ2& 1!G 2xlG2OtԲ3 3/35x3Ri%33>22ok1ֱjD2:SZ+2M;J.36n`K30 D3&''8G3s)iR3 h33Ʋc2ݱ1PB2!Ux2_ ԴU3P&Qp3>a 3ޜp|p3KT3$,322j,2%2ZMYo3f3>Pc3=Kē3dw-3bW3 e3ĩ24D~1R"2Pah2E73fj3r3l܅3{/V2X3Qe2&Y1u$ 12Kl92βt%20Բ12T 3OQqP3 ]AE3TP]dZ3[bx<3B1j]t>1=ײ43YoC3l³S3n'4 4~3-ZP{3(w2A2,3c³W4~3).44.04<(34p,)W)4: 3g5(23i]觲3-ﳒg.4rBQ4C?W4=I4/($4볦3P93nv2=x(39߳h 4$ vH4Be_46J(L4SB4ߚ%3gIJS2J(3يwn3G* 4k4) 43ʳp3ݶŪ3 R?3,&1p#1<3$So w3d,F޵3~vq3b 93uBX2{!/2-2@K0t3u./3J3KZX\ 12Q Cm3'qV3P>3ii³X3 ų3`³3NZ+ģ22v󲵢3\.4[5cU4Zd4 [}h4#N`M>4B3Yϲ.w3ϡR4[Mu4MaD4Q4?=4]u4[(3'x?_40@4[x+4J,4ٱ쀱49˕4k΂q4( 32MͮZJ44>4󻴤4!Ǵ4f34';3_v2%34EjL4bk4Xb447P!4뭝4 )4'>[54^jS464o!4&ԑ4=P 4C3g3rOj4|JС4IB4 45K4mV4Nh24(>n4׬v4dʹBQ4ZɴU4W4M$n4[`@ϲ%B4씴F45E:5/c5NX46Ŵ;4WIњ33,o+4yG5)%;50 :5O{5Fm4uV 3ɹ3m^H4۴W 5;25v3k;5.^,56 5~4QM/噀4IX5Nj!N0F57IgO5W7W35 4:AD4ż264Yô 5&'5~!&5 qc5 ƴʪ4"83#3wY-48δR/ 52%5 54">4[ ^3v"Lͬ4D}5 #5Js'55f״o4ď3K64טw5fQC57?[d5Ma5);;5<$W<4 f2%`4uҴR65CN ~505mh5 |f5.2"5ѣ3F435e5z5ϤL5n5T:KL5Y G]4P"4qʹ,5d(i55l5緵^5z5UVvr5-,4hp,D5[95/Ѳ5^Ϲ5UAµ5/ Ko5&C40ㆴ 50\n5£ڸ55ð 5Ur58*zO"KoʹNe:5E0j2J5i6)6!6 5zº5$6N4*8j6t8B6.Mu5}ؿ;Fҵuj5WvVJG[ ݵԶ&趂5@*tl6sﶬ +ZȶC{w^!g]@5% Ŷ3Y~Ő5Չ/ 5 ,唍6Y|跰ؔ7lH"buN73qu7"7'"j}#D7ؙ]B8o; 7 Aqt8;8⣛s 7w7 K37P67Ma8(7&6SΚ74Ar,7I2zE77fZui7_M70w-2e(77`6StH@8.緬a6<7ϵwZ8iwq 7(T756ڶk=d7zNc'7j&g8L  7g|%67 7}nD37,6b8U$X7";E%6zuq7B;ڷʈYe79 KIM84 ^7b*8UhhqJj^8(ٳ8i- 6},A7I(7V.}79Ox:Ei7֢Q 867\yk 47mwB%8ҫ58}8F]N҂;&CK:8F71978 x77}26jJ7ܷo7]7ϭ7˓}J77^D8[Jf/8.9 s*8շ37}h`<7x5U>7kAl77Q7E7Է S28@xǷ k7M>!7g:7-7,]/i6i6P7808p﷮d8l&4)7267 7,N6 @8vTKH84JD8{x2c6m6-w6I{,17]?ڷ8Ϧ8):8s !8S%c}7pZn37 07iƷ8tA38%77W7bb 7e>%h 8a 8-70h8O {P8Y~ ؍8ͷo~7r:e7=޷;83_&8Z8m4NP!L8i^s8T~6/6_ 7 =L8v8\8XJ8ɝ8pzwX8j/87Mǃ8Jg8Ÿ8캸eJ8c8IВ8 $ 8Y(7`bCP8q8?8Ҹ-8X[8S87_֧6ꎷ}f8zz8L8d"p8ul88Lx7I7‡J8֎8 &ܸ8:v9v8j`˸8L5|u7T|7Rη;x8=68vk 9 99d8k 7 5-Fs8i8}ku9|S19I0[9#j8X q{ O#8#9i?8 O 9i 97 1-9 {9ݸn`8Z9N;8K6b&+;8y ?9F9 Ak[9v0<`999W7^8)81vPH9!Xg9Gx9,:179Y,˸xs8<:C848*v f9ozC9?o9;T#s9h:DW3F9jC8e/E8Q08)V_49IbKW9XRބ9{]89/N'P9y ´943A8%8 s9}Xb9*YY9;M9FRȸ\9? )9)8H8|8Cvy'979$qĖ94-9߃ ]9. *9MM8dF8]197F99%'9e+69~SS_/9)㛸$e\8U8FQ9kf9Ʉ9䮼9s0!9#];=\97ܪj88 ø~]9( qK9J!99h9qs9+8#8< 9 9E9ҹG9Y¹9{0#9](׳88.&9}9ع :G? :s۹|9\~՝98Y8LU9%:\ :YΤ!:/:XYk_9! k9S8T ,P9::H f6:kg#V::U :5չ93+9q999H߹:\*:n!vf:x5t9(8XmU.: R:)"":*Gĺ :Dº#:l柺tO:p4b :[^JC:ss:ĺ}:.|*A;Z\ ;ͺ:}8|4D:#J$:S:9m:b;ct*;$; ;赺]:c7\:lӣ;>;~EA];gW@7[;nG4;9}:rt t9U &:˱YQ;t7Ft;S;#,;\0;d1k;צ:&7RQ;;f;IV˻;J# J<C(X<6!n4N=E< p;銼_,=``ͼ3ZxtF>zOPt#6:IOw6:/^0ռd5ɼ8ñO贻 <<,;<,:e|=0O_Smd܂0s<)<t$:@#=*lu;?;-;R-<_:c]<><+<9X<<-Ȼ;4X໋n;*ֻ4JW^<6ah;'>(L<=JS<TqCDVKjzǬͻ |iX p <=3RF<=/ =R<;9t< v欼 e-J<9hB9|Wp_jZLYhü񠞼w<.ݏbҖC':.<\<?6jm</d;A: |<U ZBJ廦/;8;;67)efD636;G;ߺcYc#F] ;D<0:A;,VYD<4<|U|oT%Ջ;x;y;PcaZ`ꝻZ8 <,OF6\W>P< s;;<`Q <}¼\#9{1<1;&;:e<Ӣ<^}di;7f{<\:;<;k_Ќ%Cܻt޻z4<;NJp r;?Cl:n8<<ӱ<5i<4 s|o۪_;0@Ae;F<: Aû%<'^Kبh22 9t*M IQ|'<(<`<{u 1IF:V m jΛ;%TP< <=/mcL ϛO3&(/ ;'<:3󙼁j~;乙|:`i <`:䩫7zvE;ۊ#KrLA,Q'w]G:w<;;d[ ǹWiL54; 8@:HH;89_;-{EW u;9% SHػi;Y ('V8q˻U;Y<_@ b%O4 ۙ5BDNӘλ<,:J;A%Cݻ\AnGDq:wgԘpZNmF\~n3ꟺc'm;`';聻*ຠԜ:++iMq; < m;]Ӆ;;9\4~o:Yn\׍;<;| <)T1/1EV&Ⱥ҄hJ#2Tdh;H<6q{< <.<";y ;c <\]<6<;RN;lw׋<< ;E|<7; <,o:߄;9m3Uq:9}Xg~6Ġ#:m:ݐf:zh.r|8<˟B<>;N:q:s(;^ݺZD; vrx;Bk<+<`I(I;A:*ݸOL:p驺I˻zc˻|غսy9Y麘ɲ:); ;9b:\t:I:;9 D:; :!:κ?;dKrϐ.#6;Q";x۔9^ܺ{ 0+rĻf:A]:9{;;d;ꚺ>ThƕsF9K;H;/;49)?>6B#}S3/:"(; ;s;}i9Sǯv9<+K<'3;K@;:;59`;' ̺ͻZrn9c&;ħ/ىꓺ1zsf=:P8Һ 0+9nP 2 zZ.)I쐻9 zD鵻'Q; fe ⁻qzM9xބ;ܔŸ~dU[;"v`Qb *q߈z;;; ԋ;;XUOu:7<<ʝ;;_o < y<;ƌȭV1; ;Zj-K;;2;u5;GH;;3`;:^~D򻵂=!W.'?Q(߻ !')]4;TC#<0:Fe(/'9j|w+Թ~G3 ;/:9m$%9M+X9Ќ:7:9M"w" i,{,ջ#cvќȻ ۻ˭R:ݛ;<:BL34vI[Q ;ںs;4(s<]\{ںBz;<_;;;;}ع_;It;MBOQKu깯ҡ1H+̻扬6<0z0:BL;:G:/,;N:w45;3v;K9pt)RA:ތ;W;I.:9N)+ET:78X;:ί:^lҺ Si;k; ;{;}KY;lO::b::8 (\պemW:c&; B;*;:ŷb;-;;Ŭ;;][5:!'; ;Ň;2;n:ta;CD9m19̞e/ 38d:;7;Qշvg 6B:]; -:VeF@:C; ;Y:m<;(; :NѸ蠻nŻ^FrJ-9i깤f9Qli鱔P;x;W;*: Die;O[;(o:@l;Q;;e tPɟUD:YT1>̺>Ⱥ/ ;2;Tpp;5A&iӏsn/B~Շ9: VJe:]2A P.2C%ûUOnיp9)::B;7y;;J;;{;P(:2:i:M:m7:{7;;ߔ;K:' 0jtjc ;'<5;'9T9:;H; ;Gntru-i;S;ס9N3uGذsݺT;K <[;cUxM : ^;A#<~;"9Z]:}::5D;:^95J|m F ʵg h(';:;=;M?b]޺ 20;U;ۺRʻ:m8cn/J,;"j;f::4;i":d9Q:1:2we\F;&X;:*cs>W: L;R\2;tt;YR;CJ׺;+;G; ;A9^8vh '76;|;ZQ-`:";x7;䌻_b:j=\+TG!:; <;r:-;S d;';:-7.J5u@HWm;DX;p;=;&ꗺmt}iH,0P:^;LN;Z;ȸ;t2;6:,nJ 1 @:4>:Fp:H":A.k:-4;^;zT:wÜFN;h6oţ::DK4(nS˔5`:^';4:vA9F{ ":]:6UkкqON|:J:b e;nGL:J:;1<ț(B7G@쐎:Sκtڂy혻J+欼9ҝ87:09:; Y: 9%8 Q;9Ʌ:.lTpN׻Ypc)ݺ;:ǺC>4HM!iՈTTJ644Cn:cf;y@;G;:L8.9Q;j:U)W%ޒ:>~zbrG"%b#DڊNI`\; ;Jb;O;Al;KwL!:ϑ/;S;hQ;R`;̜;vB;DP;w:B4Mkk/;;zl;6c;9n:Efӛ-mgo;;Byc;69 U %Sh:}:ń:]M`:i: ;Yu;sn:-; ;S;:H:};zo;vZ荠󻺗 !5@:T{;3;ú0j:c2aߺv:q;8;QS;;T:Z:1Ժ>2غeo:"f4;k:\1|o7Ѻj)9ܒ:S796e{޺M9:8豈==v9Fp: 9BKe9:";cM!V/{+2:WP;GHe;.O98eպk3L:co:::T4Q*%#;?:'R3sO<:7w&a:=;ԏ;;6g:q;kz;8\Կf» R!7-{3G䬭KocJ:uC+;1@:ԼR "iH;|:Nj-ẙo9,EJ9:!;#;)u:v:?9[,R;;@>:™:g:Ud;6*;؊Pvκ9:;m}@ۺm:Y:6:F:";i9xX}c_٫Glʾ99HZW#f+;Җ;};i;CEwim#MMȢI67_* )wC@:;/K;c;W;1^;"޺12P9;NV;=;N^ ?7௨|Ŧ2Ȝ>' 9d9g98V CYmfG74̻Sє[ݶR6ϩ:L; :Q&;ю';S9v!X:"1iQEt{ պ~ºչ9;K3;hd;\;'7;ڀ;m;c;Of;?:nU1;;^;![{;l;0;;?ʦ;";=]:2:;*:z:@ǟ:8;Ë;[:%;ɕ;};{H;,9k:"a>:razZDQ*9읻 U9|x;U<1; !;͸t$oQ6"~38aH+ʻ슡\rjn,/f,D4DӺl T;.;8Rkީù9T߻h;.]?:*39:Il: |<;\;;x;T:6;<;dE:`CN8۶9NȽʻ &!; A::K:׺C"gOdW :R:Gh\ :3;h,;v:;3:I::/@ hK *~N!W(%OC}MM:=3Hb;k;X: 9; ߯{9)iͺF:=;緧;w;HD ;G3gh9,:!]HE}9代xʬ)XߺjieKͻǻhs<`Ѻx.,C?o:;R;!`;Y:út\:{!9-F,9I:j;t;(k\:E~Dl;k9S:DZ:,m M:~:-a8-m$:::olQau8˼;tz;W;AY;S":®8̉D&H](/ݺl$EizZG{9L=D;;bh;0v:t:o9ȸK74at;`;&;&p;(a;s;sZ";:;: ÅBֺ :5'; ;%;HL69z(@+u#Ս.B5DA=:gL;9;Q)Xr; ;C5;K;7q;vȎ:`-tպEyY:5̺0oY;];}I;I;;w ;1D;@1;;B6;;#; A9` atRH-;i;ܕ;n;mf;9^)8(f<=lχ9UJ;S;x; l:?&sPX*\7E,O|Ծ].ԿOJ ;:㺢k)b8&TĶۻ}ߣo(Ich]R2":79;X:\q\)KG83c%:Wg9WKplk+rپؚa9b;產;V֌;8:-'9q9w$ߺ9\c4>͟% 9:k@: :J8ݥ9^tL!1`j/&";HJ/;S;;#;P;Ā;y;W=;9rB;:!6,::GF:e:ܫ@:`:A/;S>;X:;S;nӌ:;C1R7f83^U:;: ;:SE;0;;G;};N;+;:P:r;):NZT":FD+;N:%:$U;$;C^;3 ;:@t9:5?:ɸY:aդGoP:<0;&F:B PǦ:s;;e;C;쥸s ڸA:{:o:W;7#s~+NJҦ)s78S/P"v S;d;6;[~8亡]G[M^B9x ú O0e:O;O):)89/^:9aPutѯ :(58ew+]9;:;k;ur<;ψ:kTx׺8:9SPc0ƥ,nW久:dx;\;;:;;d?9m @zAb↺8C9ֆ -m{T(;w;1:2vkWº>Xv&9z:G:LZfCrS.*IF;IK;;:.^;:ƿY>> ;,;F";t{㸻RP&TQ8,3;-];R;U6;AN55եI::-9u9HF*;Yх;Ku];*;gm!;OU;;?:Ց:Ճp&D֦ ?`}:":݌;<;a6;W:LZ::!:3x!ns_kອ;"U;l϶9;Zv:o͕:;];e:{4= #%9=:(v:2:c:w;x;)l;3;Ɵ;L;:ޡ:}:27llt/::;Z :߹I:;v;=;j ;t;Z:uur8p:e!.;80;T9J e? `"o"r*;gw;k&;A;B*;?*MfDhI;vaQ] Y&5:IrO i3YǺ^1dP!;;;;<2JۺGܳ::dc::31;F:]#e9:ߕ:uJ9:D9::938>:):BD9Fº;k[f8ͧs:Iz:{9O%䶺1$:+a;N;a; ;T㑹Jz: :O4?\Ϻ]ijF垻(g)ắD:%;.;:z |%0!H%Y纈XQWY:6;<;;]%s;j;/T:ˣT;Q;^;c;:r{:c :hk:]: oa:Q: ˄ 8W9:+@qq).P;*ͺ9"P:6G[;X;{I;:zo!6ebRz~td::: ;vLG 茺 Nr:,V:7)IA/3>D2>^_Ⱥ݄ = p6"hVV:Hx̺C޺e&3;#͂;W;E1;B;*;:Pz B,kܝ )J&Ke:Ƌm;} ;8|#'jFm"-GD_ZݚvZ9- ;;[>;KIHfN-eꅒ{هϻtcBȻŌ*繃:K:pO9{`gw2: :PH9" V%;9O;J7;:l|:sz>n;ʹ9g:ź:X=9KL ~9{:&;Y;;;:X9<0~.lzO9"B7;;s:Yю=?m~ݢ愺:;;I:4nFD0; Q;Zx;*;M"֦a;j";Y oMǓغEO:U ;f;do;: 4՝:bL:Pi㹸(:H:x;Ҭ9Ѻ1㺷]9{o; ;L\9iບR\A4s8i|fȪT.yjג:;]I;y;Y;f;;`^::xl;@-;:9D:R;x;Fy:>[+1lٺE!? sdâ}\q^i:+;W9 e,:W-; q ; 5<tՂ;v;}b;aٽ:˓3; Y;;ƗZ:W.:z9hFd1|.:Zہ;?;/,W ±G(I f,o::~:wA;3;78Avl9L::>x9iRVs2N 1AN:$jX薻]wgК!Zl(lG8i#ٺhsiG<ᦺfO!֧Wܻ%LǺc:=V;{|;9 y;j`;#%:UDY6M7;6Ke;:J<;{F9P;Hd;>;:93i)k:8;#:T) '[ߺf89*٧N :Ό::g:$E:[:hG\;?a;o:;$;{;5m;{:m{N69= ;;,#;f:CL:~I;v;*:Æ:9e;$;;:-8R YF6:c,;;K9:r[Z;:N̈:+XGܫ:|:W :겁:ƨ?:9:;^;;+9F aǻt%Ȑ1n:gB:j8:r:Ui9=:jI; g;;cO:L)f[B8g-9=99/&Ժ{:5:r0;;F;b;5y;;L1d :":й5sBWຶ0? :D;}:^: :"i: ;:9ɩ :E::'9\c9R e4QN<:};Ϸ#ߺȹ-:ꚰ:;=;E:R9'F:9kvL9pi;4Yƙ:ѷ9~X 9:2Q:M;n;n,;4;MM;; ;A:9j L8T# $:Yι&D:#,;OӃ;MJ;1@ ;g BV qU~: y:/yx78jnalq)A9:Aιgom9˼Uӹ`κ#`I:$n;Va ;UA@/BFsy:^b9*(:[::'/>j:)n9faٺLpJɺT{:`:e/:͘ȉJ: :dL;L;g5;X(;/0;,;:;)^;w ;$8iB:и:5;lq;X;;):`ڱmChc4.ƹֲsɏߺ^ / {/KPl e󺆆b"df8{TvK'cx=]/giW=M:P{( B>"ѺcƗ$79>:Ai:Z$2X)w3W}ѺL쓻N;o`ߺ*J2D7QyTkfHƺƂۻ h.~1(8G\:57;4;:Miu] >:::MQ:9 c3:=;;5+ ,}ǽzM;9::';;l; yt;z;U;tn#;4"1;M;;n;:;J8;E;޴:2j53lbx8}:J;qak;a^;i:r6즸wE& BqbETib2e]w>^ӽl+T-8/e:[:8y:{:m:q;):pi wSK^::g:~x:r3ͺ7p::%:%;R:ך-)N;rQw$ǻѺ ?bIB%9f :I/9^j:- 9?9L:1󋺂R9(:A:k"t779 7+^6n26 X:I8[;E԰;; h;:\T9b9!!_X"9i~q׷|Fv v#ҹ@0;:0:|; :! X$˜(:Z:R Q:w:&S:P:a::TVtisy?7rשB<}OF6;?`;;[q:LG9#*Xnк29Xo::0;'i;': # -erb<z9t5 yZ9ed8^7_vtbS=uֹ~IԹKyrnh}Uqfey9{M9 :Bz::_%T^5~(8P:9MvC:N7:e%9ioPڹBz 9J9(: :z*;i;:b:0Y Za4:vR;mʎ;6م;s:8e:#:!B:5;5;;h+w;J;,9 [ (kn9ɺ(;;;Q1;7': r2PS9;: ;":z::h`k^J~Gc!iw :e8wd i,[LMM|8I{::2':!;e׹=ჺ̺`=%v:qb:^ |κ':;,;]S;G;D`;29;z:\ κ b:ŕK;[;,;$;wQ ѵŹikw869t.:::Rђ9;¸!"9S:DR:WZK:?"2:0C@>0̹9*,::93h',>SJX6:I9:q:;:1v:F:99:(f9≺^r @SHx9:C9s:J:1@(:UɅ:bAԺBL?e0:7:,-; :j::3:/:-;ܶ: :uč:?ѺܺͯBv5i:p:r׬:%v:9p"0ٺx"{ O@{#8C4:$::X:B9+9p:#;C ;:DD:d:ͷd8zc9}9İ9:8:"5:ڨ[:M1:$&:-9`9><::JGʹ@%]y8;;;);mI:딺r49r9S:<9' qźEʹy񺅲wm:;&:<΋: ; v;؁:V!$:C;:Z*Eh6b0кix"Ek9¶3:mߺA^kSݺ֬Ql`8:9 _P89W:4J:F":s*B=9x:>9;#C;׷:75C]snS A4S@’9$!=:Ub: :?:R9`i||H}Yb[dX"::Y%;:8N'[N᪸[ !9L2úGBu,̸Kúj"ߺ^9J}995 +j 8ksҺ?ĺމ\k򙔺Vd::*9p׺*kT׺p:9"p9::`::('=0ͺ/݈::;i;vs;4:]K0/Bb:ʲ:o:_m9ӹ,8>l:P::К;c:I#;I:l:r::9[:;4d":67,T:*::X:;Vs,;ӣ;g:Zٗ9N#f189;~;::w:-:; ;dg:8 ]9?UN$R;x>;ތ';vG;W.;;;;iպ yc&e'ADk m:ø:y9_YW˺星fɅ{80:e)5}fᱸ*:}:r` U_Mm]Ϟi:҄;U;A::l:2J: ::O;qV:Bt ƺAܺ& ạh 䘺P9;\ ;o`:59M{:5'D:]/ #%Ǻѝ:vc:F4:(&:yjXú}87dO996e9U ٹ (9|G9:˅:=9٢ùd9 $캤J҆5_9W:k%պWߺEdiY:P ;jP.;|Ob:LS& 6LC4z^pqG:cR=0'dۺc9Թě<񺉠۬pj929V {蔺R :r#;@;S0;T:bȺθܺC&9ƴa:c$:4:;G9Kv7 N::s:S:S:z9=:.:7:sd Lܹ9oRg 98 G!BN( h K W`7TM;4:;:wQvG9n\:Н:,: T9OX2=%=::ث8?A̺Ӵĺ%ʤPպ>S_Ijà:::\9XZ՗!i;@%u@8J H:o}~3[q)9a::U:-:k:49 ? 9Z89:&i: A?3mRJml9ܱ:w*;:~{7!톃:V:o:i/: cK:6Q:~C:2)<9AS99Yc oh9mk:#:v:T:"(:V;:yU־ú@9M\fl7 :zH;:b:6B:) ::1Sd3$<7yXp+7`2mƞع8Hpȥ ߺ$>-:8k:7躽%G,KǺfp޺̺BĺO,F9_:9y)h n}!C 4*ciֺ}pf/Rn=9V9=9}j:g6:5,9P[^ϑ8geR&:":Uh: Z3K9ڙ:ԧ9Nd98:IQ%:e:G;lG';{:]:3r::9r;8 ;@9$鋺σA29B:hW:::qO9W?878x989V7QT9ҍ%ɹ:;q:/P ٍ.;ٺ=9A;M@;߬: ?9]&69A⹽ӹh~TX9G"کK*:: :#:N:a4:kE::DE:Î:2::H;ݸL;:_n:W:z:ߑ;gI:9}4:{:h:~b:Fط`92of+;=2i븒s9A9Rn{9V9è::;"';=!;:89 kPX9(A::[;y;2o;";y8fοָZ\9:V9㮡-%\غ: ;-:::: :-:)B(;:Ƅ9:i9 h:: :|D:L8vdZ:Ғ:ZHfź$R9ж9klV폃+ɴ"#8:;:€:t:ܨ:-/:|C愁9m:X:N`3φ:c$:T <_9c꘹g7Bq1.RαETyu7:zH:D: 8C2Uո/%:ξ:w:-9I5L9Ղ:|#:48G#qm(֭ ٷ?&@.(!vպ/l 8՗9 8U0/9ܶ::$R:;K ;IR:{,cmf3ɡ33hA::W9b"77%:<:*;b,;w:Y%,K޹7X/:ب::o:w{p:N: `:ev9:r:/7;{ ;::j:̊:;:L:E,ĹGq>:a::=3:{o:v:ib: g::R:Ov:".r:N:]/ ;q:wxj::M]t:9;D37+>ǓR:T: ::ӕ9׺gFg:0:7آ*%9Ő9']5:Q\}:=*:|8헺ڢ\:473e\Y9u:4:*n:&5i85:)Ԑ,d,#9:ߧ9::*;~;ȃ;#;,TѤ˺UC3钅xZjVVhX݁]d::S:֘@Lպ󇿺&2eʸ6͕::er9EZ>GE'Ժ ;I/9us:xի9A/MM#ù9}:[:#,ﺕ5к{(qeƺݺKǹ,y :U:Q:ƺ:{1:# 6g`ú̺=Q:Dw:[j0/!F#:WP2R(=f8~:6;2:>º D3Mɹ@-9ҙ98k:̌:NN:,Ό9)s:&:2%:jly8c&k)"]:m:s: :|*::#|^G=:7j:(}:u:n;,;*n;K ;V:4a94:ʯ:o:E:g;vvL;u&$;˰{Ǐ*9j:UmC:$::a:A:: O:9Y'9҄9Y?8 :48$HH2:uB9 9jŁ+?.ĺ9~:O:by:Ӯ98߹IӞFv8VV:bԺT|@[,Y@7pu䥺@#ꜟֺB̹5::'4::::o::3::iҶ9m0oh\-Az˸ v8ZG&QԺܺUKʺ݀':6L6x7 Q٫9R:R:[rY%ι84!:OB}"@;າ_H6s[{SfϺu~7.9 *ޢ3&/CP*f6E89/:e:=Yfo]ĺ7vwVQ9(O9 7A޹zٞ&ӺJw;8=$:uȍ8"0@HS #4a筹%[9#:(u:VA8|9%*ù8D7-Fں8q}?PZi¹]9a9[Z o𺑄"MrYmC@9"1CU" UUiJd+B{&Y_= ƽY.ʏ9^E9@M3& 3T⺪úqYpI::1T:?۹7L~G[Q :oJ:;}>:C_:90:h:x9-FG8|H:y:[h:~I:;W ;^s9vwHTӹJN99AlS:Y^*c9a::K:nL:Y::_-:7:x:6o:M)8Dy-9!:f:5d:JK:d::L:׆;.;>ݪ:.GȺ7:P;):Phz9!:#Mh:M9N__9Y0:ht:)f:L::,::K:9QR:TZ:n:J9b+ Hè-Ѱ+4Oº9:{l y=>l=9Z:e:*:~::@:&:{p:Ԃ:-r:&`8:X:&;:}:b^ƷVk6㸓kJ=G8a 9C:W7:?9c9cX:J::kC(: 4:@ :ر96b9p:N: >;j*;;A:*+zp=jf9C:J:g:,L:&9S8g8:: :: 8Gع|::d::^ﺵWN::<;`>; ;u:8e`.99}$:˼t:9^h^ctT|kiC98C9k99o819 96: :9NJޞ:t:r:<7d ZTqa 9Ɂ::u:L`0:WYR9A9f^E ^UQ9G::\J:m"Z0պfǺk2my1mBğg91"4Q]S>9f::Gl:b:C:mM:8l:'v9SMkc:>::9n?CBru[\ѻ9{9d99:l49NH9b†ʺ\ָ[,::_:A:9E6u:嫲V999s:;7?:[:)9L9Iܥ9F9\읹Vs䬺Aκvzѧ9ȱ:h:΅L:.8w >4o0:~\q: <:S:`: M::n:Cǹꤲں.ܺ ƺc]b$ZK\u:::JW:Ý8.HLԴ$ܹ{919V"^4-B~dp}rȺk:p:+8Kn/u9d=:o@!;߿:rjڰnFk ׷9ksb:9;jCn$չ,87q鸗]ܻ~ʺ` jι=k9:3u':%9IJٹp.`ٹ+ZؒH+0]E<L9KnV{%b:*:?: 6-Ⱥnְ/m*-:ϋ:n9pc%b亢 C:#hl:9߹2'9{IzcB}U9]9@x8( uݺ[JOǾR,.F_؃8k>:\n: )ڹ]t%:0}:PP:s^:k:]:9cj1Xx)&عqD͢Q(\7%9:{a;5;/;^d:"]Uv }9:w9 hpӹlHtC t^8U :9%J~@mҺs˺<wF9:\9$u?:H:}^9M91]:%:::Q: q:$:' :S#:<9,qŹǓ. 9 ̹}ʺUr_L#Iw,9WĸsR7("/ɺ@t3Ƹ~M~9s!:R:}8qX;9߀9#u!򃢹 OκQB'sE}8:9A :ǿ91^+K3=9lV9%&ܹDl%.ĺ/),9?:XHMwOn U9i9D\:>:Œ:pŏ*?{_}9F:9O0`3{uP[^99黸]9 ޸W//ºcG~"I̺0/ܹcw`R69؁VoѺŹ9}l::9+Ѹܹ5LU0깁 :=k:+1?:!99QG34QU* w+O֧­C8٠[ڹ89H8 m|v.湚,w6L^B_( *T99I jxN}r{5 Z3ZzNo(]5::;¡::9(u@KLo-9MM9:p9[G5Һ@ 9"?txw<%( ƌXX0ֹ瞹v*y-'8~K*9n8G885r8n79i9_:9[Ғv9b:E*:*:#<:O2Whk(O<bHYC7hE8mI83ok*¹ɵs7O4:՜9* Dx9:LW9xM/#Ӹ}Umg̬fj-9߀ٜILߺ$Bh+k6: 09D 6E1Uv!e,9939ef #8]SԻ>9: :2-9951:8Q亹9: : 9&JA&n9kI :K999с::И:0:O<:6%:s':+9sݺ2毺9&n: 9 9v6:H:겸M͸YJ:J:[:[:.:%>: :"m89t:@': :n:B::::yP8gE- 8l>!:q%:P+:_Ǻ0Ǻ k,999?ҙ98Pn:r:S:7::j:.u:E[9m:ɓ:+:7&:Y'|8x9}:;:(UC׹5g::}:!8 aw9/::`::S(u:+:Qh:P:Z5:m9w /FĹU9:}c߰PZz9::E:~W:#L-9{ùK_C0M7w9ق:ރ:=29D->>9`:;t::^Y`?9':xE9湯:85:KU18% غrfKG@\ ͭ9c9 8U8+8 H9źʺZX*m5eQ:::Hcf5`9ۮ:X:7:6::59:4:+::`:::6 9l$9{ : :gC8硹А9A:W4: 8:D7|::b,9'4n/9:49&ͣ9 9a:%:&:U:9P!:ʪ: :M\:Cy:0:[9'$ 89::W:l8ZϤGF*8e:Y:3:N9**F:<:;A::#:p]w:AV9W׶Kz8O9@:~d:9Z੹m+6/:q:ڞ:':'4:$9RCyt”(l6_8L I<ưy 8.D ,qa9*8)a'8-K9 `x:K:Ϯ9D^mYZ; 犦J9A969C%): :-:_9>9X#:Mz:8]:#9y, ,趒4`:(;::cC.:D8?Q;=zعn6 (\V9}΢U: :CVL̺Gcȝ[qtH'/w::`9#~w8/8~^8QT9/f9n*܉v  =,89':(:!9e-^mv%毺3عtKlpW6.ֹ: b0Dr rGൺy*'_O˹lg_~\#8_8b׹C/ |[9L:F::}:9VyT׹6 k9kS:C:7Q9s]9@Z9;#sJ(s^:KOq:!d:{U:YL:"::rnR{q9:E9xN5.)9$:s]:f;:(9bc۹"9#:)d:Ҹ:G: z:G4:?9@`z8m::F:@:Yu6%9U:X:_:%:::G:C`:T:9TG9K >85m8L9{9"_AxŹQ9:%9 9+0:2:S!9 ޹±8$:% :zJ9g+SNEt Gp\Z#9ѷ><9JW:j:ik:9:O:+9FGa(ܬ8uɹu19`999·d:@˰::g:o:::V}888|uֹ¸/9-:0%: ::*l9x09=: :_!Oq`׸ BHcƏŹ%]9E:ɚv::8mgU85hs9p_:VvZ:?/:^:>-: C;p ::m:::} :"R::98zmgn?_f9 0g::ڳ:68ܪE9'::ͧ9:!9":E:{9?9999,,z=:tH:R@w::J:}9T*'Dwc㎺輡N!9,99J9P-B:9M:G:dH:bh::Ej:x:X::::({9i9{0:/:J9zT9j99M9;9):4::y:V99A9 :9kb998VU98i7\ m$gK.Md80:#/N:s:::t:U#::X:g>:dw7:3":(:"/9m`9U: :斣:$X:C:A{9/n87B8 9_999!:Da:4::R:$7_ r׸~A3v-}STbs )e9q9:"9#MpPÀ;H9v:XT:$":ռ8Fs(s19|M#:$:?f8jQ!c3ݹpk1/4A:pn71:A:;:$A:Q49U\8p9܇:S:uU:**ƹMVpG'Z0(q7~8 bm\9$:d:59nЌԹ'V rZ8K.< [B~Q@3b7G'':o :ir:::(49o9/Tu 7T'8ʸ zṦ) 7qD.'4FP89S9O96=c9dh9u$J949999R0P݊b6}nc/8C9r 9@ _޸] 18:A69:M9z̷濠ιcUl_К<>GdW!oeBq88PNO d`Da~g%8OXyH㹏:86I8nrf919e38xL8(` 9zDTb\%y8ٲ zY -ӺN_ms8AnNк=D15/i9}9`8&8ʤ9n|-:d= :Qķ9F598 X3(җ5ӤΧJ ˼E,cntD8^99 g7ݜ 4ZJ3w~$㉹0FvF' pNC%id9y9'99`y:9 ̷J![NWm6 @GA킹'8W@Xn  o\9z9䎱989e9 8mN+9ޙ9::E:Ըm:rJ;:tݢ989>8qtlڸ7d9N&9 :kP:ɴ9M+:2O:^:\U: :$V9o#FS:h8[9Ⱦ[9R֐99Gp9 9q8Pٍr,89P8)_B3f-繊>x'x|F1\xHUU9mI:_:p8 :ݭ9ct˹B//ɹ020 U潋 ʒK\8a7AxC wβɷRpL#:I$Bp̹N๲yh~A :%:$Ҽ9 8UtnY#9 >::;:':+͟9DK9[Y9{9n#:=#:jw8j% ,0>c$%[x1x9 :y:Y7:N:FI:ۥ9e QW6йC"9:wt:W:Z9.9-9Ȉ :eC::?_`/8ß9:9ѡ:r!:n`9l8i76a99Gñ>gl >w99.9ZR̺WF8t999 y܊79~r9UP9n 9y@9*:M,9𸛆8V9y9Q:o:\7:r':98_99ܔ9)8wb湻08z8% 7ڝ8[9U:)j}:"#}:Pu:lN:y:u8f(rz!e/GR94[:P::J:5:x:,:: и906m.29E969T9Ʊ9:hN:rl:̎I::!9 85m<(mhZ;i>909~x9 EWF3ԹULy899f[994*9F 99 9Y9l9<8տ5Itx.hȢ]ֹHAJ:2r9%E:&::4):aC9b빎v|[9D8:7::}*:g:.:G6&Tι#-t6썌8 @'&5Lѓm!0ڹ󰸄I) +-7y9z9#96jbf8[9:9D99`:AF:LĄ::*P:%:1 :Go9?lpKFϸҎ9]-:":9Ɔ9i& ʹlD9Ț-::b:<:/2ۆP9Md:@:ϐH^/"?NRMI9r99Z:ޔ::Fh:F:q-:)f9:ݵ鹶m޸#O9а9dg9h58_9e9o>9$9Tq-W>96:ťK:;:A99w99S=7}9$9#9=9999_:e9Ӈ9~9j9$ :':O3:G:b9܌ݷk82Jh\NQQNh;\(-|Y8٭9ɭ9v :F99}Oٹb>ZfXm9[$8^O޸)8 9O:v:@R9͇8Y6n9vfY:J<:_99gp9<90989ۡ9~G:f :C99>p9L9B93b8,KJ\ٹtʎ GRlp99 #9KC99sB 8F H\8]9rBC98z?Wĸ%9DQi9)>99{29J9>9w9:J::&:2:WD:v66 20)8k~9:O:o9xGpX+7T997)!(8KuxM9\9թj9 P&9}$Ÿ-@Է :[:V7? S 7p4͹;9ɝ9I9O8@L7st85E8cB-S[W9˨9ދ987 }88ї 9+B9 w94Ÿ\D/wB8KHi8*͹H`/:9-::y9Z99F99=9q99&R e Y}L)8x8.8tl=mό8;98-7df9u9d9ڸoV,¹~m;]V8OXky>8B:0eY:;:nM:\:M:v9v94~919Ƹk7b9e88S9eg99£.9(8˩v9w9m9ݾ~9 );9[9g9&m9' hZ㹼/&CѿU!YNm7G9K9!:F :i999<6ыuTXo6ȷQp$?S5qPR淙k~v~عs8ثxX/ ùi#?X!o HdY99p9ɏ?X tn 9g,93299Ѷ9a9.199@9x9B9kt9sɸw^g^ lѹ8AU9>Qw #08"9g8Q$ϸ 32H.Vғu7\8 Kp+.&f6,?"CMVŹދSYad9?8 gW68p8~(Ugh89 99C8r:WW&7Gq929P9xs4hTzu$`ҹ{yE9N9%ʽ9ڗ99/8a .9P9B"9Sx}@9929z9~99r9ZR#幒"w9=9<8B=07&D+ѽ} 99(1X"˹ ڸ^P939<7wʹxT.il+)⹲i=ҏ9q9~h8 ji. D8^l7VfGS5B[|Gܹ{Ĺ wDe;rBh *ݹ/ǹcv|DYC).!&Ͷ+jHEj6=0fgbA$y"8&7_I==9l<8B7&%Nعqٹ͹!f%#Z븏X88uꃸO1W鸹rnZ:Źiӝʄ4Ĥ9$9 :3::8*(p$ܽzXER]79,:!a9Hoۄ9):_jB: m :)9:[:r99o:9Ϯ99@ V߹H998|KӏtL 89pV965gMSe(^p)8}9w9ݹ2aQ8k8b89:(:9W9)Ok9K9S 9N9^9Q9Vc9!*94:/9ۑ+98,9Pa99 9 t嗧濩9 d:*9g9.d9a 9-99?'6VX|ܸ 9?99߼ڰDC# 9qx999-0h2U OܹP!Ƣ`hvi$XԸ!8q]69 8PO# ʵ,nA9߽99_U9*9Kt :99mļGq719:=:89.EN$`YF8L9ʂ:":|u:":4T:i:m(:^9AŖ99'.:z:::xE:,3:B9 88ǽ91A:C:m: zr:9WķIdwבIZf#I69:9Q99OJ-:9e:Wi:Y@:999W8H9D999Cv99®7:AAZ::59Iح78Д68+c@x2a <<}99Dr9cy9_09s8u8:g9 ?9/7:#J:c9NuOM9_:(k2:!:99 9KZ:ҹXMO+KE'!}~ {=Dc:VC9Q 9Ŕ97y9l䣹 `DH8Pn:'eO:0:9Ѓ8選ˬ#o|k !9k 9%9|y΍JѸ 98[<ŹPZ+8;9_:Բ:㬺:::V9㓾9'9d:FJ:mT:O%::9n9?fRٸ88k9U6:::2,:=9jC9:9ߧ :%:y: M9[izp*׹^93:R9:96h8(9I:l9Ɯӹ7>9M9>8A6l8I9?989l 9:G/89L8b:z: :Z889 9l@/ 9>3919W_9Qr99Bʢ9ծ9$^: :{9^=9/99!8o8+:998F&)9j\9%8gۮlHyh6ւ9 [9:7l:9`9DZ8[8F9s9"?9T8 jzR[9i 9o ɛ~o8:0W'::J9 :SQ:Y*k::װͣ"ۇ1Ϲ8Fj79d:=:E:w :h:,:):9;9A&8P4j8 8 y $[͹l9x':aH9~|e[R~[puV|8&-7999`99|9B9PZ9V 9\w3czY.R8d99Su8E0+p;ԞqwH˹:湫(j .ا̷9d888,B9 38(NN8>9 :Ka:+N9@69%9\θv8u"9"9L6/^\4?9j9 7_Z$ fF9S%9d"bиJNŀƹlsf%H㹗Ĺ_ظ[8ѶM$s9# H篸8[9Ե6ֹ'6h'Kc* UQʹji3l8XU7%uI79U :/!:k:q9.89c9Fea穹G~BI869O\9$9{.9n9?@Q98g899nX9eKXȜ8N98δ76U9:_:8<(5 C-ڴKKx9A9U99Ä9a99J,9z9B959TDpGKW9ɠ:8:k3:::!:{:U+:": 97"YӁ𹇊I=F!Ǹ899Q97X9LVPl~XnEou98dJɐRcl_A ͸&FmOƹPcѹtAe, 9;09X958&\8i9]9;8 IĸCъ<me(9֢9]:'::9˪8Xc yJӹc32;8p8L0(9p89 [w]FC[uiJ385v9Fd9E9ç/׊v8.8&*mf 9'YC9-9 8C]77My7*;8ʳ97 <9S9z9u9J9v94{9pC :%:9:x98>8.?99BK9{99/0:U:ֽT:m9Y8$x[78ԶH;Ϙg2S5K9Rӗ9999}09*e8J9F9$:C9::9#96f9"9kk8H lp89[8939r?8Vg7uS89w98T ::: : 92k9v<l8I6a?g&9n9?9j9y9w99299Б9Gc9-9 09(b~wE\ιYv6G!P9szD9*h98U8oܶJW8(9_n99V9|9T9UO99j<^mc̸68#<9q9i9:]!:l9_9V999_9}49 @XҶob9.ܤ9e9_888nM6i93º9H98w}99 :t:=9QQ9ȾO7wŹֹ۹̸%8+I8 f ͹U 8i8d8Ij8M8yV{~cLſv)е_7ϷǸl898939]9Ye959q9?999f9_<6:Թ'9U9c\8 89<9"J9gK9 8zBǖ״u_ж89|9.P9&'98999f9ߚ8ۯ@IGb |H3!8&19%9 Cp919R:C_#:Z :q9t :9:a929K :A,:v>:Z:r{::iK:9m?8 Tʹ0ӹa8qA99 1d9%|99)_9me8n7ze'U2M.@ ɹhb7͒99'9/7z/3`tTl%+R>Z 998U8z[ 9#Q9΄990I^9?9܀ ) +H+ʹtT&!h*G/`%#פEs'϶p?LlU"-﹞>BP9 9խd9f99ln8%ĵ0!9:g93 9g8=99T9bߢ87 9yK9o98F7q8J91 9LC7χC.;=S+xhQ$g,QyK+B8|999;99Q7,hh299n9u 8KJ +7!9U8q"D8.8T9p:@999ƃ9/-9sN4$89%9ѿ8y* 2r^k 6 g]%1 89b78$wٓ i|!7X&Ixɹ̵viN(F),w!B2;Mmح` 8mH8xfRSBR vι+wZlZ"4Yh&J\ 5Q8F8%&[<8~MP9<9j979#9zX0Oܹ!$.ȉ O(&,T&z |S=Y6q]ƹ4{0Lv% ¹YK޹:@!ߍ8r8y>H8pؕu#QD899ۧ9wJ{9E817zɸe829w 9C899 : :S9,vW9"iɷڦ۹V6Z[^;`"vZ͹1S-ދ?1ӞOىn9>#R7LQ򈑹MU6p9999[v29rݸ3W㻹s!>-"%882 wDݹ'R8aL9~b9;9DI82Y6bim qALaƐ>mOM8r999i9Ҷ998>0W9 qȗ `;EV8&H9d}9}8%PlA0x8#69p9 Ը?չ<> 3E 7h9#D 7Bȸc(8Y8$\8^ lƹۘV XιPy I9v~8^7;N,Gڸ |!7G869;Ɖ8#YY>e޳??)8R 99l8)9x!f9΅9(9985L8$0 ̷(> 889!d959rr*8/8Fe984i0858n7o~E&hY78=8lJ Q (99}9׫]9&8kϸޕ`Eam8_9E(8 ?7 $9K7+-b_5?XĶ霸~Fӌ7Q#8e%K8˖ՏƸ`Lq>pGڷy88?@8a8D19q99w9e9[9z9ǜ9/Zu98K899ppk9\9-zq?θ68ѕW99"gj98)ZpҸ+N߈\͈"u/Փ99e9@9N08Ov| 9ϹjzhƸn2'FV 7;9ot9\(9s)8 8 @9998@9Z7xzִ7 8J8H9*99]:>9ѕ9#9Y7P!a9`G99Xބ99L.8+6,9-H9826=n8ۇ83A?]JBٖ8D#8E9H9rN(8 ZJD- ⸷pآ\lUB 'o-88Ķ*؏/fy,8|90 98988H8 8m|88|ߊŸ_88Q"+䶜 W8︫ƚ [@^ 8,8 ^ $:w<{ ȷzT/ =Jr-:8Ӡ9b9)9:h:t:9e`w~38̸ #rM!`89v948ȣ6$9L9N90S5"Xjg?.fe &phU7S޾7R76P;|1aɷdf8b9!99ΰ8F.ތ`n烞mȹ!)͹ʲ*7aݮ5׹ٹpk,~NKᅸlZ8&B.88 O9:}9C-9 %FF w~xr=|b8O:R~ib+1QhE< l˜HXǹ鷹]ZҹoL ?ȠqU7|I80 6G7ĸ 8~ge7 Dp%븲g8bm9Ai9b 81?CS]ǯ㿒TX8d99|F9N8jOkq^^+k֡⩹cA#~oA%5,ٷcu9ˏ6@U7^ݸԤ=۹ĮM':}il2]9R8j7A84D6xaӹDѹѹzՎ{n919u7^OչftȺ}[߈4!)QD&9?f[9L9*9$9B9|ج7t\+Թ޹sLԸ7K"9Ƹe`8͚99v9k8u.; 7vi9s9298U7xlGʷ,:̵\ly8ne8**wEg7)8E9!g59A 8ȟѸ^Bڑ˹ɹ ngNXTh-d67"% |̙]J WʸYyn◹ZO?I6K¹088ķ? ۹b &0y^ɹt5 ;߸tJ {˞%˚Z䁋&Cȸe9͹78͹(˹X׹#ma89䤬9O9;E98L8M 87l7q{ @^N$u6R8oQ8 *̷4I'b(x˕iЛ8[ )988CE6!LXpN[ #7$78zo9f98Z:/^`548^I9Dp9%!97R!DG6SY根޹:jŹ/Czc82N91M9T9 99_58, XǸ 809U99|99M9Y9Wv9f9qx9Aڏ8A \^AiD޸Ѣ:*8p|/׹bS.6 N7&7й?sAP8AX8.7Z{37z88]k/O<8 47ԹhB8nA98`8:.8(b8wǩF ajOu5888*81h6?(vF8a͉8c8B7 CzG^q+ RW[z x>bL#иŔiY+?'Ը}f7|8X39e9; e9i9܊L9ͺ86G8'95!09s87?"8wMu88JQ84)9;l 9_Bՙc~#t: (7;8!J8=N1J"ɸaI $\JT;Ƹ}ո⸐BǶQɝXq:Hp#ʲO 8ze8Y|e73t87_9*9I8·:J`&Nd%[ĸX+J8 9_8WQc߸c7 S9fm9+9 9]81 Ƹf5Ω-$4e?M58f9u9 9?s9Z7n иMոD./ȸk| c'cڐ@ƹcqjO08U}9|9K9i 9ÿ99 8 }8 @88٨8089Q8î8 dǷ0g9*78 9 9ߎ8=&2ew׸#7N Q8ƟY#ksNs"0ܸ"U19%~-q7~G8g8pN8t7: vոڸ >+j,E89E9:7n9j59fr9i]{989w9r9GeoAI9(P9ʄ]9C828go8ˊ8E8HO1nָsYP28m~9Q9 /8 q8&&8֏8ҡ7,Ƹ:@s&`0ÄG7K^8iO>999g9)9c86P/H{!^HRߏt8ps99)99|9A9f{898)G븵M\ZqgZxH} fW86c}2r7׋]&>+ۖ'}!޹UF`W 7@7i89e99؍9|ð9ʀ98r7gQ 8D9%^9jb9(8ifHR8+97T9w9(]ոDݷ799U_9T<9i4\]e|7`E$8B9y9:=:q9@Q9PE9kb9 939O9e9;8?!"_8d8̜8JD9+/987q8#>9w9E\p7]/L7e?8G7x8&F9n9"99/t9H8渞3`$~C86)9T9?9iK9}8V- ?;!8ܸ4v<8&889 8?9,"V9w9JR9%9Ja 994P9h9Y9'98Zz<8O8|q98zEްCWO!gog88V7kA긁ȁ[8EF999 9Nd9>-8ҵL8[8,,8{yܸ'8pI9>8c we?MLѸP>pd lהa)vl!%1Vf^hgʷ%88$9!8j858908b f eI59'999Xt87tθz#L9R9Fm9Vc7lK Z 7*=òW<4S7"2øI8to9Bb9^9Í8[66Y79~얕8[=^9+99L;9Ɩ8J:[8Ѹ ^8s992:9fCoN {VCbز7ݧ8_919O-98'6#678kV9h9O{9C9 o7SݸeH-_wWd%CW$0vDr67s7ZsE8vE99X9n9Єo8Ղ.x7WD99'9H9|9F18G7wN- 78MH29bu9.u9EE9]8J@,ŸQ76\ָ37}%j hPnۤ+jq 58YYtU7878Gٷ"WL"ŸXKpF7*8^8㐺8U>7T*+aON7<78b8B9JN 98(880H8"99 99d9>][1Ѷo887ܼ~m/E9 979hW9C5\c X15.6e7V}t3wlbԵMA6j 8+;84 79Lh8dK8h,58787!6,tϛ(g.8E8zͷArǸ6ݑ8s58Ø+ϝI%8Q,88 n8:Nl^8Ȏ48޶Moh͘2|8r8W8vQ7z@(Z9D9P\9ٺo8(ϖ<0 9>3\m4 V@m819ER91c.98!8x888/66N?88EU8uFZiWp!B'7Y*8C8}8L8bh8.*#9iX9[*9з8E8r(/~>_j[4UX889QUp ?_8r9ZV9V877{7淨.ĸX!/HYcL^ '$RM98y&8o8%I 9V9I(9|8F89[9gn9wM'97.,(&ɷ>'EOWO157 9c988!G8K8q8l:8 Q8(縅q!H߸ 6&8?u8S=4I677(Oķ˷QqM8999sE8Q ϡ>*{WxR8ֿU9 [9U9((99.9D9Z]9jfY9F9R3ki6y'74 8k919S`29s9j8Z {͸T]e fVm`ѡ|X8a7d3#|81\9dx9_o99D]8U899Q8[8G9OPR94982hBܷN$7e8Lj899k781iT68;7<839E9 76, 8s9 939y99{U9t[9C8-,!iqmH7IHQ8p@8<8889i99mJV9 89!鸋'278 9 98(9+99J8888w~9}\(9 9R @7q9 9%70Nm4r1v &ru.6wՒ7\7c.8{7߉65zZ8]88G{kiU689GF999Dݗ9qȁ90!19)~8> $Ը BP̸7eA9Q9D9ܦ9H9BW8pU7ޜ8+9+V99F9H:9$9'9f9*88z9!9 9T19j9z9ӣ9ZDŽ99Ł9dA928 , ۸瑸e/8Ŋ#9XH9T\9Ą9Ȕ9\u9D9]m9_9vQ9up$99.5;9#98}8t8$9?B8 7)9[,6Z8|-A9@qs9tLZ9}8¸k/o(.EݸdK2Lض792999 9d? 8p8ɞ8:y/9.Y9b`9TX9 9ͦ85-sN9j9llj9z8W7e.8S.86 Z8WL9<9r197u9:9899 99qU9_9nM991m9Y99ik88=%98D969PĠ99I9: 9+ 9Ԇ+9V9 v9 49;T9 %9X86;889$198$2909\87[u˸WXoqw868_9W'9xG9:59F/9I9m9+g959?8vx<v59<%]d0sm. mո?8z“;ݸ&N8(8&6rS79/D99.81ݸ&Zv|S$>%7Ę`޸oY~M@c'8888#E8{r=&@81j[9%E9M9t8+8u889$98B(.ޯ[ø#jظ 8  3=z4c~?4lapBlb727a6= z֐17K7Z8"9S96]9VC9Ϥ8JhԹ]ڹ+uQAK7+u #H>FTÙSYd8r88sꀶ8?=8d8_88+>Kt 97V8)9A9^91}A9&J98j989o}۸?η819x8 ,8 A9'9}d9X}8ثF&[5 7ם 8yxi}DW[8>9a 9 8˴8C39ӂ9E9]49TY8IO6!¸7!9!A9W9`I9dt98#ɣ8999r9F9 \877 9)l9=9'r9.%59O9z8r7x ƷSJh@8o詸ٷ!m88!U887˷.^78.9]z9_ 99V8&Ԡ5x.$-ADKX\C7܂8I>7_7}3b4F88 9ȍ95l999W9 9%r89w8e8ٙ8cE7!C\SP1768{ 9~<59*9s8p8(C7X,77c'ۣ'- 8l8K9n99*B9xU9?9vȾ7÷YV89M99VH9} 9~8 #88 }8P7J8]8m+9A+9`*9Е:9z8s.7դַz6dGbQa8cz<8و"ku2 8f8(8;88ҩ88霋6":;8p89NW9g9&m9yN9a/992 9+87hB~C(88"8S7488P8847$݈77W~6S67"p887hO 236R8I,7J7T-8~_R8s 8unS 7_:J7e89b$8h8~%887>-avdF7 8GtuC j6pϣظ%ܸP$c!s7mzbߵfw-TǶmo5868Ÿĸyg77/&O:뀸JW)`8zs8P8?67>)$ݙ3F3dRFҷ`?8}S8Qk8889_8-9ٸ>%c8M09!988H38Xߐ$vи&4 rtmV<Rӷ )ظ̠@,Mg l=N≮&h`@Tc2x}l˷cYa}C ݸX&[b ]͸ EX]97PydN ~+y18*?889= 9dh8$8k8L<817^#vejE7㜲78:48L8823Q#zJl8Ԩ8X8/7ٷAJKĸ_w=Q7= [a h\ϵ69|.93v8878DI涽AøYٸzX  Evҷbs ڸ.SƸ9c`ԷղV7e(gV眷8il828"S8ou88M8]{D5O>Dθh6r*6GCp,ܷ1nyQeƸոtk ,ܚ6 X7ME8|9?@98<`܉{%178pf998D3Jtj7'U8೿8885 8笳8 9Dg8r8s8Bj8998>8߄x7 8'v7G^7&z7>6Z=a%ȸ2rZ7/88d)99G17%.K! 6ї]"2B탸s 56Н8Z8Gs57sZܸKo:78C6 !+L2 QigJ@8$?9/79d8w'G䷱I|.Ӯ-Pqɸ`\*1 S"&qʷyrga`u7}7,7T6K7=88 9M89"-9*&9)8ߟ8.F87Q:ܷދ:uGy6ˮr8x8t8:~8&.8O88 z8y(OR5ok8 f8A#939j 9Lt8÷AwFyqj,Lk7 Q8|8c892+9#998Ť.8*a7k88^29;39; 98<8m7od(  '4ܔ899s9w}98Kg7+()'Ѹ-79b9P99j>9Yև8ӶGBxb["Ȱ򼦸 67$y.7ܛm88a8|9zU9 88uiʸ| }"W)`}ƸM[7n^8dx&8*5a? t6fK8!}83BVR򷕠k7'ˇו;巋J8L?9U9L938K 8 #6#8}8B8*8.T88[998{ 8@8/մ8+|8F8$c7R7 `88)8 88oB8E8f88@{8O888\̆8U8->ⶶ[ ͌Ba`s57F>7:73v|8X88ՆøP G%a$Nη .oKԸ]f%4)'yt8,807;sf'󥸻.It8hw8`8Fi88o?98ݍ8^7a*hf`6786 /oq{yR7aB8{-8jm6[5W7R6X7[Ii8882m8 '7f{N 8788 L9o98388hʕ8!y@F) 97 7(8~8&8i818ZJ9K/9w899ѫ8 8*8\!88<8 !8@af`S %-8~ɸʣ<ƀ 6ar-Զ6L<7 Z7DɜN9T8l8]9I8 }87쮸'Ըb݄`ܷ65MNҡJLVT7@8]7777~t>lYcy5N6s881B9H88888e8}:8;*848%9SK8]7BtQ kNÈ61#\KjR3;\ x6ԓzbQ= 5Ƹa׸+ ,M 2Ui0S/z̸9*͸ y۸ϢsJr`pOacCp!.gQZ71b8NC8owp[p *tCF2(w,B{$e/OB_N@} {T, rθD7@K 9I k<$pTA10[#94ZW_,.$9pOUm\?B7EGw۸t(f¸T¸5[e78Eo8w8Ӌ7M,'{]NƸ*"͸˔?8·sȸ  W࠸p&L$k;e)?ZD8xSwBϸ 딸 @!XTrɒs;lŸ/'{"-7+R8TB858-76V[s?鸝׸@Th ;T8Jexøt4^ 2!t4p J5娸NV㸮-''r & ^66g"綶0G9ҶԠ#5858%8–7%L3z;BHHk 2\orCF: ) m@;N8 8+8l:@Yĸ-laoߝٸ -72898x88$677*`7Z,6Gݷ~8Ѽ8u8 bdoʧbG8ɜ^86'oHݳͥ8c88~٠8$vL7ё)]?#4;7d.7ƥ7U7͂7_㷹A\̷ 8{8l8sd7{`N8-j8Q8u8*_7q88޻8h88Y8sl8JS87* XƸh۸3ngOEAIv 77K 8y8_8587#P>#7Z 8RD85,8Ĥ7L0q1R/) B q68Œ9 U9;`9%N9Or9E8(7·7+=6=\77<70N0889s/9M9W9tyl9M?j9[9n<9X+9L85c,848"7̶$7$@7,}8+848?&8 bo7(7϶C88>89708T8988>8!f8&88`$7[;Ƹmmq{XgA}랸]͸ȸ^5=̞@68J8Ǣ8W6WʀC eR:<7Jd88 8[G(6HFC縊14\?,~1M6W e^f^OhU[¸P3W7N8M8; 9",919tp98h8N^86ޑϷ7O8r8'8`·68~878ː8WF7vp=Ը7U267E)8R8X8κ;6+L?*-8 99U8t8u?Nd{ޅVh78<]8ּ8j"8L8K#8iͶx͸rqdEs/Ը3] ګNOyW'{+k}(Ǹ $ ^ٸ.o] =~ }T=Ïv3rfO?,Ӹc`{F#d踆آ~\ qNM 4}:94i.,w7b>8-w787R/8θ3⸵lϴ7Ҋ zPDո-̸f"t?ָNظH !~rܗj뀸w󐚸+% q!cIĸfD&DD 87}R,{iw !?ݸǸt%CsVFY"۷ Ӭ TXķ qxZ[7w887ߏ81874Wǩķ6? ur}C6}S]ɸθEḷoY }jǸ9ĸKظGܸoEX8Dc6 SEٸw2IM9N]SD}0c_͗"Z a& u"AXX>HB![#n:80KRM:u{sQHe ͸)S2R港:# FER3{^)! _ɸoX3ob44_nY d?%8&8F`R'θ}IθY>總Z)V(r@jS칸&ELE|PѕOhU4r=L^20')a2EwJGr9Ǹ)1Ӹ^r# 78-8nA&87kk?8i>8$O8͙=8Qa187zw7k  ȸX-Xӷ]ve䄸Xpø~Ro(E$Cܸ{vW_nJ1շG45Y647,3}Zmnㅫ:iۈ~nB6g M8x_8u8&8b581H]HLK888H8P8 NJFշ37aX8Ә828o>5So+iR16Qֶ53U޷:~m3a]Hœ:yɷnK`5'888A7*i /޷[OU]Z+7@oe*?Bj/667l7e7,7B7U8qOa8i888648=V>8$87_67<8U>8{87b8xd ˸G.ʶCT78뚷 P1U?;8W8c҃8;87,vBr}^rz88588Dų8 89 9,19k88J848//8IBҘ)0S7Q8Y77f(6; 8<8i{8x;Y88ֈ80f877777J#sD5ڷƷ̷$,w\n777۴5Pюn÷2T/D#_Φ+$2зe5668\u88{8e8D 86KYB@c6۶"e֖7r,8 78Z8`ht87r`6s7z@e8O8:8Y2D8087h`6x5c7H)77~7޶⸝{rHܖܵY0zĖ4w7'ƨ71ea7&e׶477g8z8G88q8#ѳ8YeK87bҶ˗6=N8\=8r89@8P78HU8u881 9| 59^%9!88)K8DH8c8Gk4qӸC5ŀ_O7vyg8788pa8&87b~Ig7ߒ7rp¸m߸qY):hoE78TL7i0 x?7{7EB?8>8%%8^)8Ah8R8n7nj"= ƸDI-]ukQ7ޫ7Hb7J;N5ݹ^qXeJ۸şظ$<'葷w6d7kHr6) k׸QBƸP) 2,ⷂjO:E`׳Qo歷](77 q8(8q8ڕ8h8z87s882r8K>8]M.75 õ 9@5 S,=;q:R8]8`8'U8FU7&Gl0ܸH9SW?-77*6Vmj8Mϫ8oi8VB8p8+p 8+e828Q~8Kw7[a74,766|Q7 t787[888928l!K8|7F>ε577{u8E7ӶI&k̈́,\yWS&7Nֵ$:7(8s7*6&*2#797S7 Lͷ 'J0Ui1p9AS' 6Xa7s7A74Hh7,^7 +778k8}8Y)a86 e;(a>|f:0)7s$87jwY蓸``%I2=5zl/E.8ނo8hl807ª.ݷ$i )ڠ7p8 8B=8N7bx68`Էr7t;7`7D6#˶%"7^07O7g7AG[[9vj"<4E*U5^Ҹ7XT8'87|^6#5شGD7d4[+зS).uXs6 )O{srCX KW qq4gFB7d;!7%ٷc9S諷+67%w8,8k888,a8p 87 $޷? ޷ K6 w7%m$8yJ8(79`6֤tk+z5 N o񆸙 F0n*+Ŷ ?l؎Cɶx7Qb 8Ya'8ߢ876w67 7P7 7q( /0v\d86'C738ؗ8Is8D38>N7N.70*57b8VvP81-87w6`{5hyҷJF6 h;1ƶ˵i6N7g688yD76I77E 7DA[Cgj<6^ͱf5=UDG7Ӷ7;808#`888283^8c7H7cQ67sH76Ywb鷳DD#m87eX77XH6_tsE6ug^3Ӷ|666 8t8n8,Ɇ87 *A6AF88V8/8!7|+ݶa]7j8XǏ8@\8Lh7g6..ķpRCԽG4S&7}7Q7,7(\7+7#b7tzM77n8 7D7J66N88β8vS88X8ֿH÷귤&B\$677J7?777B8q88y8#XY87X ߷@ķw?vx+pŷ7n8~%8754Mߦg>p3`ZM6^7.7N8Lx8GX;8&8M: 81y8*a8^I8U8~8j88Sr88{58T7RB8}^8}88KD77777>&8ޢ 8tзpZ78\7 6~k7_\8 8=s8/88L.8pu7a 5Y(7h 8%^8b*828B`8r8K L8^8p8 8"8V08T8l838tδ7p7d8.^8h8\a8F8JG8ge8 D8~N58qI48]Xg87]8+8WG08*_8ޮ8HS8:b7z6^ciR@]Sa5o7_A8k8083F7e7/"8k87{vf6Y7\N8qc8ӛ58ZO6ߍVY6<8YX8w$\84T8&e/8A7R8$M38G?s88iX·Rgۮv7%8 8Bڧ8}8UB8V8;5~?U[Rd}+Ԫ޶|݉5ST7(8]88^7׵889i88+8?08}89:8ì8ek8v7M7q+8j‘8K8s89Q8!8H8N 8D8J88f87p8^Z8e8:8hi8G8\747k+8888ن8P8\979&98^b877еX 7O8 89>7|77A7r8J58w88P8WN8] 99H 98x88mMI87•6D6 7;7"8U828c8`8{8H8zڊ8yhZ8-7B8M88H8C8fJ8M+777/8F8n8z8788=8 8l8o87"7,7ْ8 *8e7T7Eg8R8̖8^8A!8 88p8Y8v8>88l8SQ8aO8U7jRrTّAIwIhs$s6v7<(8!&~8Mcd8#84|8888MÄ8@`8ܥ8kq7#8;J858I8j8-n8>888%8+8%8mi88a9t* 99-08ּ8h/8q8}7 6{65#6\~6&av7H8)l8 ׉8l8D88[g8?d8 V8>p8/$8WK888;8zp8?V7 7%7,l78(C8.N8~e8y8Ě89g8b8HV9 9888:D8 88ݵ.9.959%9{297*8ܓ8B878678%R8%ٔ8u8G88B6?sõG<7 8J687m74 >5es77E8$\=8'y8W68˛888MK8=Y87L7u$877uC7N 8<|88-8cͺ88w88(~8co88a8a8>8#88Ac8!7EG7P77e78[o8P"F8F77767o,8ЋJ8 R87鳷U 6P8Y`8`K8^7W7738j 8 78WXD84ą838I88sO7K8Br8uՓ8Y8Q8S8 8Mŷ8@8>8:8]7 84O8wo77@7J8M}87788y6p 3dö4465J6yẶE7Y8888q}88S988!$88A8?8T88-88v8U8S8i=8h:8kF8{38k8uI8]8R8|898^8xJ8X7٪77? 807@88888P8.8788,88838%8J8[,8}-8 (8v8L8%z82/828FY887!N-b)7C#w7{7m/<88{86 939QL9>.98v8`8Z|88ç8`w8Y7J8'7Y)7)7<88 =88J]9-99a88Г 88U8l8\898S8'08{bK8M8t8788jK8I#Y7 \Ž h47848Hd847$777q7h7L7g7[%758@`B8 7D$858c8M8k88)HX2_d~?N"^c7D8.88x8J"8*b^7 g6757y768!8)7 77V7_8&j8d48o7670 8p18 &8j88?888W8ER7$ާ~Ogzc88v88B;8,}8.8/8 }8O +8k7]77x?%8S8V7z7n7>7 7p7E77 o6$`7ʿAz~N÷N1^55 K7.+8޷?L3Ƿ6̄$6dNr5BD7B֠788$#8 17^7šx֋X;7y]8 N8.kr888 8:w8m8R'X8 p7bW@7T7l7&87@7"827W7, 5@ 6k5]67*7176ޜ,ħ6Q7\888!77rg'77-7+%813C8zA8V8+O8:G8W8,8O8$8(7e6C]7F7 8o7׫b7xt7A2E8YD7$x t!0)G7+G7F7^?P7XS6+7M=8 88N 87P*6%u:R^GYSv?Y/%&η$ 7Q<8L8}8l8(7Z&'1}s72777D8Q78X8DU8l=6dܬw?d)%ۦ~h3_ˠG_eض{7/7ړ7@7$77C6% m[2>7K888,O86H"} "AGڀ%i="P>#6\kZVZ86N65^61717V6)6.566|ط_ؖ)A_ 惸r'~qluES$I?'@8;=̷b``ica۷ :ۂˣ">b1'W^+ҷS7U4[#`n2UqN?dCU=s߷ftԷj0зCh€з䷮6ŷ@ͦ[|a6CU7<7mf7*6 X"jշM~d޷ַeٷA*MOE c%.Yz7ʹՖ5F$7 \7eDﴝ׶&797R#8NqN8KT8G8_77q7ַ?77}+<6ht65~ 7ɍ6Ks0587޵A% ֪(ܷq#咵77['7 nY×kQ8~L26U cktSַ6^$.rPc6BN#W«GP[55%U5IGط޷q# _t$(TIw60 7vZ7{7:ҷתfWӷ>^~?*Vwv2M.54"7 VC!A-ȷaj~d|Ʒ!6 9sV|϶÷tviS7\8L8>r-8^6b,rmq;#7787CQ8L:7r/84^88E76xT626X6(JLQ p7Y7V 7m7*6ŷWFKQYٍKOx573儷Hնd$j5}6K7A7j6 6 6xo5 7p7Dq6sl?|ST4Qbi/@yn5e :7մ8@8)K$goVB9 L` ?[ µ|e7x&7ނ73s7R|7g5HҌ7#8Rh8)j8Mv8(7iB72VXF7^7ę7-77&v777"8:x7ODC6O47䯡7#8S8,v8CP98774X'7747b6q6HONH/\oH67$778 7GE7n?;7j7#^S76)7rc7*83888 8&7i7{7x7^8u 8L7Z8x7#78xL7G77r,7x16?E76&aǶ-&64u66ͶwXKPɷ3=D78^L8V87L7Srr֗ oǛ5`V"qQ7g?_7{27X8977EG7 7z=6N޵ڵWS78M?8G8 8~#8s7,7P-6777O37NN7N7437NƇ7m7.F7Ź7 787̒7\777lY7ƶ@7p*6?OB̷iE[7 x7*.6῵.kN÷x)ⶖu׶{<7ב7R7y64\X787&7^k6](76 7L77ye87=7%܂P`V7.6{5ʔ ㈷!66G725'FU}+ٷaη[| "O㶚 "~%77<7$7ur7]T7'y7i7)&8ٍ77Z7 g47x5Ha78þ.808܍7Z878*8,M8N88J 817B>!8xo88r7pX}7(\V8{"/2̯E铷hs6`66aa667=47RPZ)ַmE!~/ַڧ#77 6vw˵r^un6;76ٚ6wG @"H'+M8]!^G{-ڠ^qiyc'$Z8JiA _ 81Yj:xULS /="Ҥ zԷo|8Pb#7҇71IFtN 3BCASeUS/Jl$ &8lUn6\667c67Q78T6'Ql{υƶUPwumS+;娨7a7]7qG27(7I7 7t86ߨ\.⿇/rCy4=dIHSY;`ȷH/q) z"gطdW^A)7E6$`4/q..e @nף̷*p1ˊ6;66ȷ{ VgK,a6FxVFv#@hgI[ 9T %Sr:.`l XF]J:}jo#39<(g\7[gs'\[ڷTƷ:킸JEʸ9,TvyeId{"-k82`ø 6AIP 2a4~!qCo$Yp*gW(yALF]$aq]qⴸ2hꈸp_hZrRX(Ѭ릸GYcy/`іVwm}b_i6alwq>`c|$Z#h=SEX_*Ij#1Ozؼ$e(VE&٨ ηw뜷DD6?6j;̷j2o^E>UM$; OhJɷPW Xʷ#?LǷb)ٷDa8﷩}#zm% 62g>lo·k"l81ͷ2'SY=6b7nk7%7e7F7ds7~7c7-758T%'637 8\!83?86O88N7L7ɵ6M7{ 7^;77o77ʅ7b>77A ׶Az(B|;N7_6QY_6-$g7o7)7u6e\ڷ(E 863BA6Kd7t7NM7K@737Y6ﵗp ·[c%v÷)%D÷S}7Br7776Lֶ5ķt9*ao{ɷԷt.0] D66O ө)[@ܷG(f <'3=tjQJIǎYϷԷt4,*;t Fy86{y5|ֲJȷ¶777}7%7!7_o7g|a7Ж73@6H7B#Pٷ=ŸYkz3~[(e77[27@7JX5aj.in'kǷ$pO~࠸ikEƷU" 㦷|v?1Z2BVdkbB;i-.G&& qdJ×nz5U| g۷"?ofDxUWiGQ7'97*ض[ݷ5-JDyڼGT3"@4PXSa7YտC|T$ Ƿå䛷sjt$1g:~.m([Icp^q=d\~66d^ 1)?6-$XǷqtzⷻ7d`:'E3uŷA`E3iIG9}BU D՜l 朸@̦֭->淌]Z '숸>]78iq|)$޷`H 'V퓎sᓸDXkftV-`gǘm5ヸ_ipʱyoLp-E>XqjO!cۣ¢^K}t8e9-E'R;`fxwrM8A"I 0j)4>ϷǷL 7EI%C@p49;}j<׷0ILN6`ʶ;6VP>p0Iз#k·W T}2Gb=K^!􋭷O{C}kG裀gO%ɮ'5Է` &AzNh6<F/q I..ᷦD1M 0طjInŜ"'n {~}U 'MxGLM&O=ʶ@ ·6N3i:k7P ѐm]Y|ܢ^4a~MdwG60AD&Uh6M*-oHZ='÷B u-ts2 6R-8Ƿ4Le]2G26BVM/=\OuZ8/526B5q0zA] kնLa'ȯͶ5X7V϶Gh@M4%9ih̶x kb{Iú䷸ L>÷yBQ^H* ,$pѷ :7߹U 6$6-7q@7J7-|G6D;7u*7 62F ?p Q1~嶩FM6I_%N ӷ 0,~ISv" ڵѶ6ķzg];9A#{6ᒁ64]a匷M^d}F$"C Vlە67T827g7<7=cPͷ {LW3E{glƶҫ5$6z6ɰ5r*6PK+]*CnjB nN^c5?i{QI\Khubu)nKn6g[ķEη U:톷KmK&@6w){po20 -J '}$R ؃ }7ϝ6cշjU_NUed6zX7{/u7L{699;ȷXG6`,ڶǡw"bӷMbl2ٷFշV kO[qGQ6`b61ƕ77jD6Q6n7sW7r678I%4?|Ķ9 U,e6#Ao D+_gBU(û<~*Nb)66*7^u7T777 ڜc񠝷R,SQwf"÷ŷn~d $3<3Uطč$;ݷD ?i%˶VP<鿷le$˶:#se<rewt\P?dbFb]S+YX>%Q qq^G(N=VQ=r7 7-76Dq^rFKSR!ӷ3CݛjCwL2ū5,6:ȵK̿LS VcDz7\C\V/a#'hAkAf(;P(ʷ$ɷ謶ߌ6lv{$/3}:z+P%0Sus.$óڷb*%-*FoJH? HeȶCuCPdEE_TمзE۷i${·6DW~qO|$*HTtt[_W̷ʏwA 4C:緅I$иY: ~WP|޷3gj8*I6>?7NI7Z7Hҍ8j : P'jDSB"췏R g4Mr.ϩGߑ鷢A563@SQTTnxXvB]w6ٶ~E6 ď;dr9_c bmzuP-V#>U˷xB*+↷fM+vjk =ݱŷ/0oOͷѷ'Uᷓݷnⷾ>9t޷-j޷P1⑷Av7@Vr'[YMǷcKFChcLwy # ηs]{p67f74Z7n7,7-77JSx68D۴()ڷ>jօb9Hƶޑ[-w׷3׷K+ +6HѴvkɝ˷$@  ޷e~Q<з۬~ՋoH}񎵇*l4[662 ڷٷ]aRB<:a 4r#-KPķBڷ+«BO9dᶪt8‡ud66A6 7CiXfhQϴ^}I.]طkƷ71{ 0:"#44@qͶm+Qz>A%К" LֵͶ_u;fL]E4Vж?L#Eƪ!jQԌU蒷27f758޷mJbQ} ,_6tFkdjӷ X>}7 77_67BgzEቶֶ5zNĶcGٷf鷛.oj666жiRѫΐAX%Hkb; 55f3)tUcSaYu6UN+5&7EX77_7"t26kV0XO%dW7$7U6Tl<%34*p^ 7ٹ6׷/6Y4L7z83.8&8/7sA7^5VmG6'7(|6S%5Ҟtܔo7s66777[7x7:f7<"888r8uG 87E7ic7R78>7 '7I>&73*7m%x7ȸ7†77w7^7a.7"r70s77}87/ 88cL8:8C8b*87u 8B8٩7J 8+07*`7j 8} 88G(8F828 8 8]77B7}76CR77~7Y8r 8'898G80#08F7xd7$68/7>777R7<87l77(7B7J7$7z77k7v7ؠ6KQ7K\6$S7Ġ77W87rY8/ 7 8>b8nA8pLn8q8yL8SH88&'8XC88C8x%8lt8ckI8Y8k8=8b8t88 r8ֽ?8)888L8RC8p:8A\8gM8te8 a8898^k8X_8728cCL8HM8+b8jN8S?8XQ8\78977778!8ЀQ88}8O88Ȋ8p8hb8Lf8b 8 +8p8:8.8#dV88Z8!YI8|D818p 8"8`f;8@8ߒl8fF8Y M87,|7jI888P8J8 oZ8gi98:8I/J8L8x?8<8o8o88k8"88\7R7-77 q 8S7o78t7b7l#78sm7q77E7s8ړ7?8J8 8c87,8$ %887)l7LÕ7!7aew77 E7!lU6[B7R7{7t7jPŧ5ϵ6ަ77xe/8O8,8e 8,7 7ʈ;7$^7?77%77767S77787>=7R&777\7.8q768568/8 w#87v7ËG777):8C8*K8GrT8B8{8jZ8e{i8)e8c=878+>8&D>8nF68/V8y8h^8u8ZE8]28v68#Y'8](8Q"8R7y8F]7/n$8Y8uP8N8\8߇7y"7B8 8K8f=78C388O<77;7c3727F7ڂ6Ǖ7w7kn7u7q8i!8K!8W8/$7sv 7|F64Ipf-M㶿357"+7xiQ77I7_@7797e7[g71Ƕfm+dG(F~qp>41e75&19şPPAOZ G!Xe䶌)P7Ye6}SP7R7oM6%V7=;57P7Tz7;7 786sQ~ܺ5b77Ov6z*4'C8Q]Z&rܴr/677w6*176/t77D!7 b7n7b7¶6}lb r?! ᢶ<3@X75<75E7[6Ka6WkTa\o6O366l6J6D7.{E7H.7-C76U!9΅7&7}7^#77 t7y7O7ᎁ67/7 7/772$4im4Cn_nõuE/7s.l7aa7O77]7; 7b7dq7[7YD7x6&i6m.8LsB'5B6+6뷣7V77;F7G77)7O5#06\6t0ȶϮ667+o7f^7w7d7DK7917I7:~77;87~0y7l7$737Lu7o]7&7v7 V6׻6X-Kٍ5-ܢ6I7A7s7778= 8}7a77Bt6GﶪU۽cft6177In7b87A7BN7r7'7"Vv7X,7G7rњ7Xn7P47)6$6_C5C7)7n77ճ7[7:707 )7Y7Ea77%8,o77+v06D#2 ;6Q6&Զ7Ҷi777 7b87+f7>Y7h6D rn7ac7A7-i7a7V7778,8u 8{81777%7X78 !28`8z"p8}d8M 8i7<0U7y,77L&8U8fK8)8)8 187ͅ7b7?$7m7s8! 877 77 6}6SM`7;7<77'7']7 7R8*;78w7w+8G8OW=838=7O+7h&7j7p[7-n77é7$7i>8&8}V+8IB8&8=7m8747F)7͔7Ja77757!7ͫ7_ 7 8ִ 8>8%7g?7 6?5s`U6&6D77d 887,7p)5F#7Lj7N78d077 Pa7M6L6w777e778̀$8y8]-7Gj77bo77"8hO;818@K8;/8t)+8M7M7*7:l7kq88880F8 uf8G,8z847-u7d818,b"8'H8 887Bٻ7 s7<7Q8_I8Q8|i8]c8d8c8'8d7477N_!8e.78p808(37Z8Lc88v8v88_'88w7 '88P:8п%8!8t38'U82t8n8l8c8V8B:8R8G8_Y8&K8=8 8#779887#C 8*7Z7m8?8aF8֜@8KAV8J Z8HD8Y 28>8&8q8g78 ?8 _D8#d$8a7 88X:8'f98Bh8t8s8\888$98J,8_8 w8ji8UC8Tl8Fm8ʍX8+*8 b8#?8e8oN8V=888u-8oM8w8z8Yw8Y8/=8nb8Hcm8i8pP8D8uf8"^8 l8K8&[8`8d8y{88+83W8w88NJ8qn8o8V88˩8r08G8H88H`8ei8-6N8 888"868j8j8h8g8߹8vVX8m85C8H68b818]8z"8J8f8YC8A8|8]8}8{n8-8)887 T77|7i88y7*7 8@"8Z8m8J8z8:n8Xv8^q8bq8t8o8w8fa8r8|88r86v8!V88d8ok8|r88@8=|8۷838ޔ8hx8|8i@8o88&18@8D^`8-8;8}8T8mD8b8ȃx8H*C8e28Z`I8q88@t8q}8nBy888v8u*88s8!b88$8/,8P8@88+88M8u88;8 B8'ɖ818&P88T88-8L888ڲ}8,z8/]8۲s8Ma8-Bn8i8x]8 ׄ8}8s8018y8g8ʥ8E[8e8Y8NV8B[8DS83Yd8o8ت[8Y8-c8[8W8s8Dc8/818[838x8Mhf8ؾH8I>88%8\8_8B8%8'at8N8J8V"787s7T 7%7JS70 8S,77č8dzO8Ä8>Ke8qq8w28, 8 8.<7O8鳻78RD8o878h8V.88x8aV8$8h88?L8b388~879[727>77772o 88#88)8;8@ C8t38a8'8հF8u778D7@68<28ZQf8ޔf8Wf88.u8m89`8/8 88ؕ8m$8Q)8&8'88Q%8G77Z8=a7N88cm8dV8QZ8"{8=Z8/i8% 8#8(7/7y^7Ì7'7\6#77%*7忳7677y!8ʐ 8=r8eI8=78M} 898Z8& 8=8b78Q8(8e-817* 8S$8.8877q7[8%8 8!:8@8#77L2S76mM046m%77:`7898t=(8b,8: 87\&77 8u(8ܪ88U$7(E77 8O88v8i8278e7#8+8{;8eb78#8Hv8r8r8>d*8:38^7F,8<8T88#)8*7e 8"7+n8U77777m7877D7܎77E77M/77R7r"7H657e6ϞO7}7V7)M 8D77747wd7!Z7g a7E7E+7 7Am7p6?A7q7q6G62'6N|57$v7ɡ7T7w7uZ77G7I7t7b7|7R7W6mt7q7Nb77@ 7.77,7.#E7dPި0q'6ˊ7Y7&8N7H77eŒ7p776C7M?7r6!ָ5ԼS [ @?~+7c7Oq77q$B77$N7G7b769!77@7Uc:77+}7m7P7&7 g7N7[7W2a7d\77 8#!8 87n7*8 8Q<8n7˕7^K7E6XH{HY77β7ǝ7KO87kU77mc7{7`E7"88CF7=.7q{%6R6"7؇N7r7|ՙ77jm7u7C7H_`7`S7 787x77+77cCf7w777:7"C7̬6X{ 5PP7uDp7"̤77r7j-L_@76 .7_R5w' 7o7bM"7#7 N!7l=7d6?\7:7mC7#7s~7_G6bSL5)dlO7AUN?5گ6A46O6+xbKd8;fX56p@7G61eQ7 P5 6B7}4}7r7,7f7׸97 7V|t DmkͶΚ~6>6H5!7'aH5b)Ȑ5Z[!6ܡ6q?6a6=4{ZKuVy8 6,6Ḧ6sP\O젶COrqdl5֑6`66W&777XҚ77B6ק{0h|D766F&766U=j6`:*Y>5_ fM^Hگ#A $1ZI7KG7R7z7/@6{ 7672Op촉s65  5Y~77{7K7*858%7qX7H6ؿ7C?J6 *L7wu7t$7nk7\7V7j77B777+7}7"k7R 7 76iH3Qõ79{6t7 7n76P"7 5S-6 7qԾ5z7+7y#6Ĉ6!OOg 6V(6 7J76R$7pG۶ L6777777U#oS̔m ^7+77Y7:Ԯ6U74Qٶ|6U]636n7X;65y̘8'71T7#77O7c"7P26/6J$7&7O7 797An7f7m'S7h!7X7<8x7 8>77d57*u %6 77Ʈ7w77t7Y8Is8V 8877y?7{]76n~J6'=] 771376@J6seh,h1D7Zi67R7lO7 7V57 7R77Е7|774 8ܶrZFy5פ5$06鉵z5m@P !^ 5ȸ27# YH* 63$6~N05]N dl\5OrBMF1!)5baz66)7U\6;7776Mx6657*6QL6aL7966a7D6ŒZ75Z7n6{7pĶiIZo5Ժ6Ӷ '9񎷈ZUh5-*% -6 {b ~5g {4_w+u>6eY̶#á·v}h55{6%/C{`Ȑ8luۻ;Ƿ m\ШN< .۷ӷGȷշFַ)7979er6ﷹqP6wm͖x_ȷuŷ>\G`!~÷7շ÷Z;ͷϷWշ,QDEW `ӷ/#i# "&׷؞V"]?+q7ex 7'E%)BGW#зۮh"F )IbrƷ:9a#$S3B6rdطScvԷ+4hU"2_%*D"0-W-5V7ycMo @bW׎7):,;?*K 5XzH?;෵-+&J8I#ݍ /3"_E6>+~[ҷ)з $TFGm,e7E˱EN4·SݼTTԷZH:(+2%=Dh$7>+ 1,إK78-@xW/C-N'3U-S/:|@Mo@PսCbNFER{A0AM0}y&>;'XIw:\ZdV@^A31Ɔ'Z B{$Z!uԷXlзg Q/dBG4,zݷVį߷dYu/QP";#@"R,N//% L=qȷݷuBѷ[aEX4  N!\alɍηD˷) AO@ͷf@ȷVηٷp˷ϷPhʷYϋ\UI Dη=D綘J 7 ={=O3[9ڦ"ַ˷ڷ " ɷ1Ʒ%ӷf귄᫷wT`.` }(5SE{,`UlCǨ3 VoJ˷m@蜷6q_v0zYV5haȷv 2wrHzܶ=V~ͯ&ŷY֠wT2/v(=֊q^#dBõ-웷ҵ[-q\ķgcXzŬи.SԷErpr&ͷM?M/# Cݶ4)|أ7vnϷuԷڷhF7ll _+4$=4i׷ķۋŷI̷dy4P&2"p@$>1#(D:i]t2ٷ5Ƿo(V^Z*涥7V'c Ҷ ob 6]:R$DܵͶh4`B 6J*665]5g6 \鵼wkV Ϸ1?}oKPǷw&L@Ȯ˷?ǷV淯Kݷs30垷&.#{(B1%9%1]e۷P;iU% VG {kĢ3 SFLq;Ge%\FϷڡ^ٷ}xͷ8ӷķdRUyh·fY9*wdZ ȷPַ* F6D ԶeɷΨv ? H@yH[r*/$,n&? &@H ַOc9vRҷkzηȈʷk%'Pg 9!P55Ko[,FYG<* Է ?@ P  p#跡< 鷑 NJ_F>&߷ qN*UqBCo2 -ԱR D\h(з& ӷRSAݷ nF=_ l!@iЧ"Kط dڷ`ȷ4vʷ+|Hdg 7AW:gizmr`Tѷ h_=緞M]طjѷ`.oR ?*෱Z< ٷ1·N1od2ɷ䶷ŭ޷ڷ(2SǷ: ;s]unpLMr.T(t!& ַ -Ц޷ u~ @&25:K6e跋ɮ脱L?O2< 9/Ke2 ";ܷl# 9U'ԉ)MG6fXN-9>(T  7,.Y<+O,50`.(;<+  7U" b"Ĉ(H)Qd5 ķ96ැɷzq**h7')KYAmC MB5Bj"Cj"gշP ̷X5 Or޷CO߷Kѷ9nq Dݷ,"ʷ]зLַu˹ķo˷2F;÷!HE “_:q ."9cy$&4RǐʷCӷap㷎ѷtY޷ | b:ٷI}ֶ緲̷J󷒼!&p.$^ 2w  a-SB;b~z ebE| 93Gj,e-[) 'tJ("9~峷okCyUggZw Dа 6 "}Pӷ/*iWX% Ϸ-LΓeI@Lύ|ʶ<ϥ@a淾Ʒ}jAɝ ~`abjdn^y&[CϷ =^Qٹp/jb }&v1 'bF4 ~M2^xLԷO>o߷#kiSѷ6ӷԷٷ̷rH᷼ˏUrrMG˯v#ԌLaN*1$|)+F*H2?w > b*ηtyZ x'brI׷8>淥kfɷ3?ܷգ^p«~SȷAW"⻷d.u &ZUv  ,}^Uط"+(H-9cҷv?3cȻdF·sЮy#[:T 7u>Bfăp÷EJ{.ɷطڷ74*WǷX唷ak"GsLEMVB<هnQ2:TH$η䷈ȷU\ J07ϑe69 S5ֶ먍zط^)՚ O$}[C7/ous)4bqpc׷(7O _h:R˴b3S m55# St}my36˄÷ ض5 '6lvIЦJ"+]2X ։d6d[6!76&64HGk7Z B6&D756,Hhk6`u6or6!^7͑{7P/ 76O76M=726276K 7C5TD16y`@uY5趋9Q6c6#X6]4(~6␑e6 6w 617j7c77yݗ7ۮ 7'<3u=d5]E5o?7&6eg7fpg7(7ݣM7:7S7757W7р7\77 K7g77얻6)S7e7T7x7w77A7 k7|6L7{7Yq6 ^7i 7sl7F\73)7a7i27_M7_7666t"7['6Xp6W77|Er68Ƴꅵ/b5럆r^J7lUzhS=66O95/޶;B3 qA5@;[עѶc6ʟ6 v6ڟ6QO66cV8¶TZR+5Ŕ쏶#3 ۫S`OVY{qٶ̟sv۶ 5Bn 55(4[!/6^6孶54mdu@?G眈RC6>c67c}6i56m=ѡ5^ m<鬴 յK uA46S6^I6TS6Q6sj¶ 5g7z6ܫb=95׉5u-6dն7 7al5Ӷ3 Yi,rHfs1 O8 -&+ڵHTqEM&IsٶT{5ci.6c A+,2ڸ55XC6BG[YxPXP'-ֶ- :Ŷ&*g5h5w YB %,EN^@3r[m 7ՌW6KpF7z7˭7kH7Y`7b]7D07U7L6r7j7Cr627q7!7#7<7al7(6[46&7GD67|7I6y7Z\7&We7~7m(7dZ7K7YE7Be7B7`7.S7;7_hs7p7 T7f%7n 7[72b.754lgA7(i7ĭ7έ7ߒp7и7tv^7^7[7>77!71778Zc7am7"6AE6O62E7;,7777,778%7\8p77e7y^Z707471e7@78m28x7618]/8g,8:^87'7֍78877?778ɖ7u/8En8-88:8ZW87Ӳ7} 7*|77=l776@77_J70P7|7|7[7ح77^J777@7Tc7Qc7T77X7k7H7Dk7| 7 S7777 7H77IiM7`7n 7:kp7Z7.-77.W7Sȹ777Sȸ7R7_~7j7977768B7C7 Ǜ7Ί77[77f7&r77l77c7,7sS7&LU7ݾ77&V7al7%17N7,R75"077˂7@7 7/7l%8n8⼬776E66Q[6o/x6v 6`M6"ar70C77@#7"7879o7|h7]7v.7/627!77fyf],7L7(I7厞77z7 7N>75"7e7! 762ty7637xX777W77a7k7j77 6i787A6c+76s7>7:J6 ?7O66H77o_7D176 ut7 w7zL5L/7"6Z6;4J735f76Y/6_7(6:'7 7377{78=U7'7k7 5L7Y a7_7EZ7 6ܰ6/77hj7ҍ7775:7 777 ߐ7g7M7B37*ƿ7Fo7w{77 77j777v;7~6{786L77? 67օ7]f72[7?SU7C7L7y7w77~7e7|bq7`G7{6k6]u7@777!6'h77˃6c,77gd7k767K77^7|r7H77`G7 76'D6-$6h68Q07Wz6rQ7.77{G7vΞ7(37N7gy67ഡJ'l76'666xP5}5?M6q>4J 6^ o473pQ5䛀ݽ׶6O7 h7.3O7[/Ƙ76TCK76@@7]V6Wt>7}7B@7$T7BS7UJ65N=166@WS7737x7&]7uv6;7316t76T76 l7ƃ7I64G7Q4t6Bk7)7:6:7{66I|>6`76{RZ6hԔ6)7{5 674O66Z7[~6S.6dV~6dL:J#06|6u52ِ6 7tw7?6섺66A86{6h7{u6ke5sې54(%6#0774:bS7 6F07OP4Bl6n4Ւ7Y6-7'64 +7Џ7!5Ԭ66𒂶,g۶6Lү5ɺ4pA5K5ΰ6(47+ X7vlf7s6o6)7ya6l5u#pTmJ5%7r6~N6q]7+70k6F 7fB66ap?Cu `3昶4p7@N7Nڜ6>+2ՖcHgPs2?ZOTF/2. 8+QX7`0 5S e@x݊C;ʶAI~ $=3p_f]="ԶyzU4j6ܶҶ*Pp6ɀ$?mM;ն=q|4ʶ޻tbA(/2vs5d)ul1-J@޶eOe6hhASG2,ENXGM'}\Vе6MZ ,v64+ 66kE6wsݶM nr5B6r636K%/6Y6A.f7 6U7"7z 7g7=6Ο"7HC35⚏076.[6S6%6Z"7k6چ7b6Ȅ67677S7̛+m7:7Ι7 7|>7$P7vl7&46C6 Қ67,~6Qm7>7Vs7H=V7y77g67ZI71^5| 6,D4<7xU7(77r77Q7FR^7476DU7k7G7ՙ716m7g,56}7;7`Mp7H#5!w7߲7J77YTC7N'B7yw7xP7?7 *77u77r6}Z?7G7)a7l47t7g776 7l?7hC7.76'7;6J6J7g76!wfI6h'Z0\6Ox77.>6߽7v77707e7;7b,7sE776n547-7 78B7VO7m#7 67ۅd57]7777!777Sg;7<77377)77G7M7"775z7>`7w$F7*V7)7R7w77b7Fr77rTR7V7-Y7꽏77ڕ7#ֶ7=7ut7277١7,786M77t727ӹ777<77&7J77'77F777_78L77d~777˽7*18D7R'8~7C7w77b8Ƞ7887)ػ7w7E7N7Û7+J7b7~a7777۩77hݏ7z7^7\7M7 4777ڭ7P7 7ų7h\7+l77O78(7H77X7.7&47787EE7s70746n7'M7 727w7r7m7Cs7q77d7 e7`D7+77"78,78777777bz7z7E.7ބ7*777 N7M777z77J7tW7.7E7'777C8]#8* 8708bV7y7!77F77K7777L 8/88*8b&887l7_J7T877d&7a7)77kq7E777ib77a7hI7Ξ7V]77Q7q7z7)^7z77ñ7hk797O7nj7S7Q{77N77"j7F7O7!7[*7lAR7E7 ։77 7Z7wq7^q7q=7T7}N7i7i7178j7"7*h7Cr7 7^7Y7JZ7D3}707Pu7gSF7zX7@7U76A7,X7X7E87J/j77RA7d757[r7 78z78\7Ft7 77ݍS77dWy74X7)z7q7{7(777 I7d747:#7f7,K7Im7t7@6Uy7b7l$77x17rG7c7z7f77Ԃ7p.77ia7d,7.y7 6 6!6ˆ7M" 75Kb7t77<777t7=Gk7$b7K7b7]7)76n66M66Im7ؔ7#7:$7Y7 77N17}L7Z$8&7"T7-^7|[7<6 K67O1{5֭6r 7} 77?65#7 971j6mk7\6 r26%7*6j6yJ7KqȴBO16 .7q:27Y7~7V7:6! 7X6H6T&716"7D\p97إ666sKɶ7'6U7Z7a7v7E2716]7K07s.7ȷ,7T7"C7`71Pk7A17k77貉7<7jϞ7;7M7;g7޶77p6562 76O{E]%6*<7˜5lem7wKm7 #C7 t7{7fi7 7/7r(6 66yn4*3#766sl7\x7H7L+6c77^;6c66)6V6"7?7 3Z46Y?̶j44!61!|6J7\6ɚ7z7BoU65`5g.Cp|"Mv6[;X664I7gf7B7M7 67B.6V661i5oڶO 55|6&784|6e6bԶ!6*D7S,>6e5 - U 00 OQ2M6^4y46CH5i57c!66r7$778t65 7x27R\6ݠ07G7]S5W6aMzܮ69X(7@6i@ 7[:5bm59S6(-5P6D5:c%52J6@e4m_ߢ4s3љb6d&5+Lٶ|ǶyпDا6Nm|OLHjP5苶4xWE4CFxB6"!`7n6]456\v6Ѱ46z65^z6f646i7;ֶ,CM5f Ͷ]qIU$5q6jZ5Va6K6'W\;6t!5FP~4r66;76.7167bs6NcJ7Fp66 6;6Te6i6[3;6yH6tg4 a7B6g6"1<71V7k5l667%62176A7HI7 ^6Z^6/u4(0N5`5K6L6.6yC7`65,7Nr6;^6+76+7k7݃7b7j7\777XjT7/6JUq7Ev:7fÙ7š7h77e5׼6v7g'7 77a7qR7w7ē7=M7ς7q6X:)7[Y7Q6&765:7)q7577DJi7e7!7(Y777s~77>77j7L7wc|6e67677p7t=7\7L76Pz6[W7#D7|7r77aP7y;77W7dt7mn77gTQ777e7S7G777)7HQ7W77.8}7K7~J77CW72a7R\767ü77w7H7=78G7np7/7707l77gs7,7 7.77\W7F87c7Lf7|;7q76 8yZ7$8877f7E77(8X7%8I88y 828?Z"8x8 `8777Á7f7e8#387{ 807v7x 8{7w7j77܏8!8֞848$ 88*8 &8}8r.8f8Bc%8(8IP7*8#'9888"8j;8%8%H/8058/8:98688`'8d8P)8;C8#8"88R-8f>8788)8Y].8 C&8U58҈0868&8Y08((8)8?8M8ʣ 8-818c84838,!8y8W}388^e%8M%8s 8/784 8,8/+87L8v;8-4858"848$8688E8S 87!7I7)88ڬ.8j88 88M,<8`%8|88eL8ɘE8e?8C818J+8£&888(88/8]K8d385=8E$8K+8Y!8*68M58iB8S878z88_8E88+686!88/8S8|+88<8778 88 08A~ 8K%8 8 >8$QN8fy7)88&888-A8-88*8+(8[$8%7}8888|881^8B8+88d"78087!~78]7877Q 87e87&8rr8fs88687\!7 7K.7T777 87:7X7l*7=F 87Ļ7L77& 77 7j377H7o7"7b7>,7",7y<7/8Y7˂7F7.7iF7už7]7 s7 74b6g77X77ڹ7T7B7R77 %77xy7|!57y^7M6n7%;7;m777f7rh77;Q7Th77>7777777U7[l77Ş7/7wZ7X7ڈ7)74C772B7#7_7.7q 797467+7 7l/726iiQ7tB66677Y7,B7l57m7\7%70(76t7*Vw7;66G5qW6d7H6s696 `6b6{ⶑUǵZ̶\/,o+bTi$7'F,̴?Z51; 5D6u-5Rc6%?嶘 "Q  eAz` Kqui p[<~~fܶ.J2*pXp*#DV#;+ (5ROֶL{P r&X;ݧA (16E 6GʶȒ'&)C瘷Ȇ젷Up˥fն˟=0q>_e k-=tz'ǞNIֶ@+o^U̷ʷ@oH-*[68_s?.B6Zk۵u"k|Zl`O7p224Vօ(5E{`qFP)S=W&׶` .TǷ뽷4'Z ڷaNN0>DH;v) qkIA'itѷDZ"gW1ҸW@nVOCqŶ{qV ZN'|&tg5 G6M% 5jIg7ӈ ߌr7N<6B=N6R*76:7C.7Z667D\H47S668%45-.U6(Zmt587Z 767S67Kj<6iE56 66*K76 7_p7;q586(6È!72~7n7g7z7C6݅O5'?7D3HR6zb6cCv3aS6}(6^6+2y6*36687.#7q6R6c*Y6U6[7 6`H647W 7q6&7(4u66~66ݶ6qT9Z6^6yݝ5b 7-ճkÏ7 77oT7eJ666aI7]73665'6t_666+6^M"6f(1647d<6Oġ68"74365݀àZ1Fw6S+7e606Y7ui66Ӿo7jg7U&77 R5c(~rf}56_6D[60YF06%::66gh_ݶ윶#46:z5f6W$Y|(ۃ6&w6=$q5yH_ YI 52 .գ6]2`6 {kS{h5=zζv06v _,I6l.4ݥhk46JG̢BBp@ҾV6c3նx7:6oQŤ jǧ2˜o6BHF$eM1/kC50 ,6g|[_*<~\}qF U̷ڶO|#S*Gz1*PX5y._#Ķ=۶ G߶ 'kLY׳3' 3^·{fI-4,bĥXu?]{0Gط d"ѓķ}Ϸ*%#Ly?岷B!^" 2ŠķrJ۶MξvȲtaY'DBʷY%گGጷgŷ7>H[E󄷷I9 CܰKZ4c̞X5\Mķ!$n>h$+J8BV.K+*Yk󛴶tat$mpR&2:5=aas6^ 86 ;|f 5 Z6pSʶF Z6 ~66Vx5D6[6[KT5m 酶쬶2뛶556o涢1/H%岶vұ϶|׶Q"Rɶ{Ri3V5^4|;µ.aWI5}׶Ҙ`"9wY K=#v 6N6w6:%\6E8*i5{/-6׌7Hζ7lR5UW$yMXԘ!PUr˶$h6!&7b7F6Z6s37Nj6N|6mMʶT|`t#p: 趚uf67h6ðv7^n7v7_B77')756ˊ3fzar46Q!6ynu6}#5677Z 74 s6ѥW7AP7"77>7#q7<6^X7X6%7 7k0 6Υ6 O6+X&;E}U5<3̙76)U77ADT747]7p7H(~7|H7i&6^c4>6B5467G37#M$66X|7@B6 ^6zw6 7ʫ77|7G757G7i6`6Aa 7zn556p76c 76ζ7}d777G|7rQ7+7<6*7&64*n7Kj66.6;6;5*7{7Q: 768'6Q37NH6nL7S676ݨ#68{6c5"6|\7B77776bq6zYĵ~V]Wc&2n66S767EY6=6c4uNWx6ʏ75-6z6i636.6Y6&~C!"6%C H̔6_ԴE,S6/o j(6ćHHq!l"ʶ =a?&>*(~QdѶ>HD0Q&6IS 55jG#ҳ:|,p3 kQ -Y/B~ V0쿬V㹷&ַz1sLxjѹUڷ̷3oBݽ>_ŷM䘷ѷLT?8˜tMַOަv R/z ;F+@O]krő;,߇oַ ^Qme]J熪&}ZWkZߎ|R327_ P iüXg~FKö274OD[с&uCǍp 9Ud%0˷fϗJ/7X{;]^wX7w(ŷZ@]YʷAܴ諜!w*XϷeńQ;A]$)ķloΕ/}R͉" g^{90 zDzglط츒:jDk7c"ڷ/90跒fh(3v淆-@X?<ȷyK?|p'#4:eloWxJF*]>lmD>,cZzE5-5Jx"PI6յ6ìW$Ёэ +/޵iN5"UԶ?5dz#>D'76A"U@űpC))6 RӶmڲ\jo߶cn Ђa6MOa6еB6<677%オ|6`GF]9^J|*1(m@3p̶+i6gǵﴶLW bk&^ض4嶞4WRXK6n2{6au 6 ,K466iܔ 4hxED6@5<7"V6o8ؒ58͵J6.6ۼ667sy6\666p[Q7G7E6,I5}6 7%x5K687Gv7l5+=ȭ쭶O\Q&62޵ M66Wk516/˴?QH4V667XTնVk&c1(5&7SB6g6cd6%7Y6s6{&7뿬5Ie3Y6I683q.s36[PC6lpu5 G66O7W5cY73767q7P6Ux7Cz7&(5p76C866Zlp63fڴ657776 37适767\R7rJG7(pX7$7w7݌7x7o77b16 t7"7;ي66$7ϟ7{766ut7ET7ǹ7'Ȣ7)U77377$f7]6 6r6:7'+7+7j7387 wv7N77"G7r7C76Wo77H 7 7 77|L7;7B7GT717 7׆77q\7m,7ʦ7 7tw6Jt7!*7O7+7)o7(7}77>7C)77E7 g77y7ū7)6w7=f7́6q? 7! 6B5G7.&?7;7MΚ7<7Ɇ&767;$.7cN7k7977%A7-7ӧ7"s7Ab7H7ia71$7gŔ6y7X6<7u 7~6E7@7177,7&7ձ7`O7?7}P7oB7W7778N7p7I770b7~ն7ۦ7ܳ779'77a7 k7}7.=7q#77=+7Q7Lcn7w7r?7777Y7>Я7Oݠ7^7T97*7p7 m7UY7ȸ77 {7V7)7u7777 P777g7g7CU7[7v7Ң7If7#7m#7S7|7=7S7iR77h<7 7̌7h7T77Ei7\e7VM7 ^J717au7~7777kf7A;i7c7۞7۪d7v!7"7Ro77 7|W;7qL7X7w6Y7n$7xΑ7x7(M7 L7GH7n7K(7W0~769Q7"6|C6*,7B6\#7O.787 70@7J76N177U*6⏶4) 5ɇ666_7e7x+_6X687}6ϵL7'*6M)6f6:6pC7݂6H2676M5\57j6Gd75t؉p6.C66Z5>Nʵ-6<6T6.7Tt7V76?6pos6w5L65Si; Co6)776Z󁶶ilP6H.667U6 7s6G66~V5L6U6xҵOG6 6;6n76?6ZӦ66|65G7&6 L<6KT5뷶O5 [2"705~^ 6;:2<66\޶36sQ?L5+sVL*3[-bz5Ʒܖ=7ä0Kp]𖷟l2o(ӷS;ɷaN.ʷhǑ$,%΋ɷPҷ8\̖{0U-Ł۷ֺг޷Nķ^ᷩ;}ȷȷɷ2޷÷ƇܷU[ڷ QfVE܃Pv` ׶ʷ6 L n*/ bpc&T̷i9Pѷ{DI&SEU=K3׷RM8MM%zj0%)5VQ܁P12S׶9v9=e/<ϤJ:/SBU|\njTrvPh3ZBȯd6*"G>ш,M<8 Vv*UzT @ՠ~hrាصM+5 u)uDȋiT{y)2ȶʁXͷ4I'v;aض0q^ )6vLYebN*gI(N| F*<ȶ? %9q6w=~16ѴfG=W5yhiqƝa ӶƶH0G$[UF }Oc0ծ6ڶ#ҭ66mE662(#6ہF4~!˶JU<6L<TKv*G =+6:yⶪ]k 66&f695Gp6t6#36 n6~7gr7R7^56"7H7i' m7!*Y76θ6{6.7E77m77o7$7Q9V7F7 6M_7 7in7/67L7f7m747?77W7Pi7sB7ܤ]7u7>7Zk7{7Ҡ7Y7,7g7\77zʓ7L1[77hS77,7َ77{7?z7 787o6a7/=77=7e7h*7t#7S7o7`tU7e6787N7/7ٶ7^m7477b7776쮗7777}z7a777777=86W7X"7 7K667֧77Yl7y7x77g*7Jr77}B77¦7㳛7GL7@"7,?7i7#67m;C6*7x57`#7&7n7ڢ7S˞7P7a 7U669mf7E767;7H6W6Fxõl7or6V7V~7L79g7T^7E%76V7S74H7ꑵX6/6%,67 7#7m75J777)7^647-! !77c%g3]e7X%6Ch6RV7577=69ݔ6T5m74MJ7876?60 7`7576\;7K6SB6187[)6%6l6y;86|7p5-7 )7P7t7`7#Q7 6p7679*7:7R,7m6/7ن6!7<\45-,776|+"7P7dh42p406+³6W6&'68r5666㺰6N6K571(7V776cg6]77 ^5Y6?=7yT 5X6DJ5l#6(.5Ux4(t!6U6y67EP6LdS53w߶yO5B*d5?i67,27677}BOd7-AX,*caj6|̶)/U)V;dG5+@6 o5,5)77f555P筶z\X8% v^d޳Ky'6Bpf3{QhN*lvVö?m6#rϵ Z3p4^>"ʶc*]79zO656ؿK34i8r9,E3{51JmOof~dͶCޟǶդFTѵ.G˂Zr#H3ifC<?]5;l!Be TAAiPQ36 5fζ5+5@ &RC1,Fg5{D5TT"6^ӵe`z& ֶ S5 ]!ڕ'Ӷ{;4S-̶q+}A.zbã)q>E Bi+ᶞY#Ҷ}ڶ"@ms͞VȉU/JGSQٜʷIkN('I0uJ)?5;r%1 ? ѾGޛ5_bd:O5Nh4i:Vl@`=>񙷆;*ɷBNX)IԷ̷aG@~)S{2JÔ+ęu\Bn2/K=3Fk<Ϸq6} eCTKp 0wQFΔs | uKMw+L勷f׶Yx2uնc &/+SI8Pog#JRk4e:,Y*0ȶzc6E\5_6h^n?+0:V޶/ͷN/l#1BgLb5b:lzK0 9$o/~:wsQL@ҋ5-6$ٶ5YR;?RIㆶUࡅ7綿K:O ^iC=}&2^"\r+6Fz7461т6;y646M6MI钻75XGXZ& 5goCc*"64;x(ɶ26y 270} 6G$526tz6d46&Ii6- ;6U涞4x4F=26<öלi0]6ҀFխRl \5_6l Y*67}3Ⱥ=6L(64Hz*y ϰ~y׶L3xZ53XVRT5\󞵑8ѶQD6Fh56_5JyWӶ`6VY5rJ42Ž϶W5 ~, {h9Ƕ06?"O6R6rN5Z)i6w5<:74@7z7 7,67 7}M76W6vS766:'6B6145 7˅6%U70777p}7#7D6t7ȗ7΋7:27jq7o7d7 0i7r77?L77Ġ7 7d7)Z7U7kB7L7Ƨ676]e757C7ﴴ77 7 w7 7$ݏ7>t77L7_b77Jn75'777hj7E7 7Y~7H77U*7` 777f777c77w7 :7Rv7+7 j7g7J67~78r7٨73777_6ϱ7&77G777Uf7$7A7X7t747a77I777A7v>7wG77T7Or7|7vT77;7XT7H7L7737077~77Dޒ7L77~77Զ:747}77$a7s7s 87 7V.7h7U777S7JR7`777l7S77R7777!7t7Me77_.7+7h7q7k78,77 7 7VQ87d8g7<7aT7 8788[h7/7Bo7Z8 7@ 8x7a768Pv8888̈́8@7 7d8: 8B7j87 8L07SK78n7:[ 87%8!7: 8`8.v858@#8.8T8C8eJ8F8 8 8D78L877! 78U8K8O8x87Ɩ8 8J7Fk8zR7 8yG7"8v8< 8Z 8ȼ7h18-8M7(d78E7787r8ծ8"8)v 8 8W8}7887873f7_Q8&8788T7w7w8O 8w 8R8Q 8y78t7ژ7U7O7p77o.87K8U8F7S7D7s.777"77~77`{8787f7 777^37%7d77mJv77]7t7v7È7#^7Wx7d7B8r7>r7k7 77q7u7p707C7x7c7Ua`7m7V7+7Q7l>7u7 Rd76797x77^7|k77bb77܂f7ͩ7Z7y7Z77E7B7777l7 7!7%7w7е7p,7̰7E7I7}T77k 8a|7+7E7 7-7Jt7]7̢7 N76!77c7G7t7O78ϕ77M 8G7 7u8777'7k7T7N>7j727'G717bQ7⡿7ג7 7*7"!n7B77E7`7p771q7b7٦976Z7̈7747&i7M7<7a377ߨ76C)7kP7ʘ7ax7+'77!7`.7=67Q(Y7I/7n770/77F77h7R7 j717+Y77/R777gk6n@76D7}G6n7ͅ7փ7Q7##A7Eq7Fr6Udf7o76ϖ7L7g77n7Ѽ7@7g*7g7p@97 `7^6B6l6u+6f!7?U7,!7db7c\6dxS7)76B,n763u77y67D7g^7_77"K77"m7 7A>7'ڈ7]ߖ67vY6#'767(7`.7 u6e7iV6Qp6c7Xt 7-7@N766(7@Y7g7NPO7:$7O'7H6<77&7}6!787ڙ7]7A7ޑ6%a67ؙJ72'k7}76646~6yo776=!f7b7Hm 7`{7>6[7 C7UJ7%Q7o737MXQ77]P7p7 7P6 KM6Ӏ795Sl7e)7;Q677O7J*d737Q7so7mq7 77":7}17Jõ6v4j7Ҳv]67Q<:6B5=57}6{/6 6 }J7<6 6Y645dFQ65^B7p5c46%t`7mpG6x.7!Z7#7彧5)362j6jH6ȿ57e6F6l5 ˷Q6=k 3M$6sS.7666U74m76&7h]5A5:6p4G{p6O685Ӓi>c. /66P~4Xs6e "64{a67ZƵ:6ʈ5P66K5h66q61۶Q`6`6H345Mw*M==ÞxK<Ҷ#66y74gX7Yg<56 M5axo66zA6=6*:557,Ò4ܶDG{v#VrC2Lwx6[Uѵ <6g6>6\g66+6M^15A2|=5.a4L\6.\q6m|Ӷ}ϵ60^%Bg66͵۩6mu:7Qf6ˮ6 65R5>F6?(5b"6 5Atʩ6^6-6׶6.z55ce6U9[6 OgY!6r6y~6 6" 6ى3h45v6}:54.ќ"Ͱ{I?k|5[ʡ6Ӷ_Eֶ4ڇ2JJG7$6r6Y6 666G}6L7-6H777p8L$Z5|GH 8IZqmDbFUiӟ Ғ666ۑ6ɴڵU6P97aq5r+7n!A6~.5MU6Ypm6"6%7Ȧ5T`e75З6zI6.=7_7^f6"76uv\76`hOi7$66N67Q7937j7&y7T7e7Q6'7I$E7'7}S7kW7*a74[7JZ7f7$;77K7{6 h6747K7}}7Zol7Z746 $M7]7]pL7E7776A f7"7;r7ݔ7Ж7'979774+76a7k7J7L7G7q?7m67 7h7307?G7k7XC/7E7Br?7ݡ07Cc76'17Tw6477#7vу7i7A87~5f7C77ST7c7.x7)&D7)77s77i7or7Eʹ7.7P7C7q777`/7>7p7`/{76-|c7wӴG47?7@7`R77O7a77777e_7a7g777g73777r7Pu7'R7۫7 K7ź7 77: 7MK7Ⱥ7T7П7&7~7-777*7777Ҹ7J7\7˔77q7V7an7N7/aS7(Xr7o7fA76~O7k=777'27\7Z7ݤ7q7 8 77"776w7yqv7SL7B7[̆77Ap77%Y7Xˌ7a7 77վ7e7̔7_75~7z77j7 |7$77_7ww7%ق77Δ7HE7b7Y7|7$7e7Gs7 7;c770n7:77]47N7x27溒7x07&757t7677髒747u7%7Q5x7B#7 70 ]7?7>M7op77gf747$7͵7b@7n77%7K7:ij7և7 CH7?i7Z"7FT57_7"6{ 7_i7e7VOW7e6Ql7L6N7X7!7+07iR7w77ը7C7I7wt7f7`7V77I6sR77697Ocp77y7{7 76"7 7 6=!7`Tp7V%7g7}-7'67 7ך6=7"7WCE7@7Du6&47c 7P7(7773N7V7947=Q7h"6h5@7766K6Eo6 6db6 46r]6Q7ٓ7,7^}7X7}j77f717Hb76x6E,7/۵toNH68QՂ6ң6I"A;)7d]6pZvxQ7-0Y64 f!76V7>b7f6h66-Y7<6$X7cf96#769%7F6o757Ѳ6d:7D6w(5F6"۶6έ5x~6p6h66[6~7686)6 7Uj6;]Q66lYX 7(,6m"OU7 j35A~<5{$ϊY~667._456E5)^o(c>uL6c&6H`6;ySK6=%%U涼m6?6ާöhX*ζ~kփ n&\{Z^W6_:V65""CմTX#6[<5ӶAN$[#AmBU259=Wy&˾ж<K;3䀶 @w Ϋ!L胃C#546645[-5Yd5H{t.϶u"496y٠w5DƄLӸ5j6!6h 6(ﭵ\an'}6&Qi55D646^6<⦶ѣ^B4_6U66E7`6 6CX`5c6'%N6/(4@6ҽ":˶Yp:Ƕ[ekҡ06/0 b55R ƞ괶Cܴ˛,|Kh5LϷH' f8kжp.ڶd66%=sC &'B; qE{ȑn] lŷ]ƨN_!-I246Xo?ҶIcsyHY.FpG0-0 y϶_pBBa~}26Klrʶܴ53m ڶgU Flo5Ͷ8}6߹PKWy KZ琷&*Cª.h~˲#2` 97{i*|?3.dX?|#(Cwɗ=,H5#vkH%FܼȖigi-׷_SǷni%.~w}ɶ*Ǘr{_MPշܪy䰷xT0񊷰K^ VbGTDNj/ȽW82bm-8YԎn.ve8#CS|ͷs1!ط㑷s[#ujٝ<\u5pr_ Ӂx#Jʷb/އ߽Cĝ޷9nEs"]v́5Cz/jun/ꑷշ+T[|jͷMݩh)$.%X4[XsVeXlζ$Զe-iX7#0 %siyGy[÷׷CVVW̒^Rw\L#@䊊0죷(DWk@#!lgMhEvqGKĢ9 bm"|ZY#/JFR Xf54K£#l-w^bŷׄRUkg`@joBMA2ݶoC옷VFTGD³pҶBh 65dHHlI^u^u鶒syhGKB-#Aζe)^{涮Ԉ5ӕ565 w,G665/ӮDѵq6oZӝҶTU϶,YJ5\5f*4w8U¿6֩_g 6Dѡk6"96hd6f6>ȶr64955654+6bP5u:s5N׉5em6 65m06vl6R45.6Xud 7*\Q6&6x666>67p4|Ľ3}6;69 66G7C6j׵T p\36QGҶGe6C,lwN5Ѷ̈́55ا65u͵xO66[6"636=G5גv9165Rb(6]ҞU6[i5KQOMf6!v5zW966= 6[D6I56!%~6܆7OU| 6l660CO6H6L 6Z6v6'6~WK767fK7#5 6Q߇4C6(3=t6w<7?F^6_Y7GK7]L6J6Tl6:~6!66#66Cp66,777U8O8$'656jY3-5d!K\6Di6(d6q~o66!6C{T666066:6N6C465`6A ' !F{6@6I]ܵsMCS`Q6 !HHa輶:fF%Q;5fj!['Lnٶ&w.33:w) R>UVތn-Kg^57v ,FtxyD覆w2eO`=зZg6EVlڶGFShiTδ'9Ʒ[ҟp1ѷ 3#[驩a .홷2ѡ2V4jmKptɷ}؃w}0շx<ی?·9 U9;sKi&y=i"̵o8RړY#迷[{tuiΑ#e ]8}:Oau֭՜Tqʷ1nѠ|@s+&(շ>Qҷ}"?ӷ@AFՎ#Է!,ᄷz+VӂSK/Օ36෷Me ӷIŷGǷ~~) |ȶ÷e2(摷ZjĿוf੷ҷ7෷`׷ꭷ[МSu;0T@,Gaʰm ˷)T̷'"ȷ iH}}9fmɷEȷ&CyN_7޷F*PL_Ʒ@ v䧷oϜ勷Ћn ߟ8rG.g{< }pQyVp+f쾷KҷX]Ʒ0]鄬)·,c %^YCd=7LyXŘI+ⅷWil׭Vo^aϷWpƷ?зLW'9ŷA}aی!HLh0Rg%'˷tB[Q÷nIϒmDe^@&GnIv2ѷ؍ݷQષ'޷7SDlѷI ѬOjWN·Q ̷5gݷ7˷:ѷ3C׷hr̷[0 xsϷoѷT/Ϸ>e$XԷn D#(跂O쩷2T wUͷAH㘷6๷w)| Z1Ҙnlq+tČa-3p',ϓY}A[/M>Rf𔾷.>U1mK0hD̘]-K[<#<%:݂XYI?r@f~qH2X()5tYAMR@_rDhKm#ea/9Fe*ZՁj){S4AqqN6'V% s&DݗJ"rͶs0=^$(p=ѶZ,8% *]B(1c~ c1%#zq(ƚ/e ,Zܚ%eo2%"]ke:\ZᅉXvqQ kCk=َ/Bdj~0ewp~ uX`YπHWv8ΝHg0a -urcŸöHS18[ND{i?ݮtM"qgY\eٶ?i"16j)(Զ, bT=El2BoroҞW4.9D3# 8gqlPolƶw $6V68 ⿶M6@죶heZ!U&oTf39vl6;3u7϶鬶ܻ Pu& 3q嶙*3Kf0( 5Mwz?66BM6=4`N%ܵ o&a6N5ֶFej6W5E6$Isb6*߃6Xh66`I56nʯx5$6g-66R6յ׶*6tL67Q2B-J6ڱT#D6LI`A7ȼ1g\T۶Z6&5'ζ^6L:6, 6aV6x6)oq鶧ou/e@L϶ǐ$Զ5sS5J 6z_ 6۴O+Ք6T7;A6䛶D$ITSy06YyB=E6s60 6uiQ{6/ɶK6@#3,l) =p5K43C6%.76c;6V-6把6l@ce+6,oRL658Z6s36$X6_4_6sNIU{695k R5 6a+6b56ѐn5S66\6A?6϶6u=5J60G:QY6Mjb6𼶮61440iLV1V M8[5+;õd7Pod6F(,5o[U k6_5Ĩ6%?65MT;,Kow0,B=7䃶LME9kk6-!4W5h65HQ3]yx*K.P6ӶE4̴%F5 l!Ѷi-4m ~flF.V?oB= kkضG'NܶjB(LbDöS5=R/F3.Uݷ)L7d M@Pq*3IwA`ͮ7KnBĥ>ɷ:˷ ر M^r޷)TWsDTR?#P[֕~4V"FM$ZspHlIy9ַ٣:0ExW^?VEYDBd" Kl#ngrđImH]2O+wQڷrk{+ʷxo^zd#1f="^`Rx wP<:o}0>Nn|nѷܷo-uķrlTA(_ZζZ϶9?N" qik4ⷛ^ͷ`ڷX9۷8\i[@#t3>(ͷx-pD˶O(=osW(8fH1 8FuWL||75Aȓ6f˟G\zuL/$rB@:-hrݶrәB@yq8E?6lc6)c %˶R4)ENyO"%ᔶ礶Ѷ[|fco5yw 3εuQxHLNޜ {NO_9T CٝZ'ؔ`Og.M5/{|'gkAnߧ63&tE!ÌkO|Yq P+ ޶%$ωxQ :6oŶ3zXжPQm,'1q!T`'Z b$G;:5 6Ri8>6'y6 6_˗ݓJ[CڏfKc)gLy5d`K6O45¼bơ5ʖ\[56].Ҵ4,}ّ6.#7#Jz276668S=7h6I*/6J6}̡6;l7Dܪ$6h6/6 ^6WK5hk60X7 b`6?77 7\i7M6Xr74&6T=76O7%H7/V7@6D&7iJ-7as(7X7,6Wt6”7 7DEd6e] 77JZ7Y7D6ۉ7%7)7(57Z6zh7$73O7X7'7m7QZ7^6 H7ݪ676B\79f7=;7_:7w7TT7R7V7-$766玚6676907s6Я76-6v˾6>%7GP7ŵ6I 7#u7l!7$a7#>7W0727n666n6.6)H,6n87_77]07k72)76=7>66D7km7K6@7df77'6;C77V7_[7&57{ؙ7 57 7P7?7)7ck7k77s78<7)7Q7ֶ7)I7~77D7G77(}_7 7}37{746277֌7i)7f77077d97dH7O7X7D&7`7o`76Ɠ77=7_7Ť767uib7N71637oQ7v37Y˾7mWr777F=A7{766'7&66g&7A617e7m66h7|66r6#6=7m7S(7φ7ŋ6*7(556jx7~~$7D6*7G6967؉7;7H/7yS7 6q762Tb6#ĵ*6Z.6B6sKR6N7M;7]\7n<6jz77E7^*6q664bXd6ԇd#6(4F65646b`8C 6I5v!ʵd[} s8fY49M'BL-xFb?3Ķk-r)/p7&c߶ RRAdXU ˈ,L wXcV@^ln„7 rV8a*AB= d'I:p-oEo]`Y$V]a5ӭ pOmo\z "Oly$BS ",wFQP(3oh3 fd l%,n׶2I @dz9E&\/$BS;Ewöq+*Od#6#Xw޶5aa|G6&`U$R)N Ip4GX2:5\1E荶ҤmNôv 6+6.5!A bFKx86̣6vSFv=}`(`67KvQWsԴ `eK{5n5Z|.6+T1XU6,$6C]@y7ǵrH6 |:( Ŷ!Ӡң4C?s}@寺8zOUCrX#(m&4]N HǶZl c+ܕ Xqն[m2ⶎWW F,ZvQ:ԊL;fBO|Fi8@> ! x 68zg ((hp#'n4?'ܶи"`QͲ0@N&&h\ݶ0NK36qG\+6Tk+p6@ĵA;h5|m񶝪6|o56`3,6f*7`7W6OM757n566I)6C266l7 ;7}79"N7 g,7P7n7z6 7^%7c#7e7D"7sQ70 $7fr7s7)QA757Tn7u6MM7u7L7"c7&7R7Vi7Uv7yM7y77%;767 7!77ј7#77r7W҇7'!7767I7 U7ġ7m7 z7~77}=777ډ7aM7ԥ7W=77F7i7i7y}77(7;7n<77.7c7 *7e77kW7b7Ē7j7 7i7g7һ77%7i7g7h7]7b}767 7^78(7%Z7 -77;7E7[N7DZ77[L7d7Y76I7]^7]7h_7n77;^778%)7A7S7h7i7i<7 "7=J7Ե77_7<Ʈ7Ɩ7>7>n7*7779J70 7r6.7B757H`7h7j7u77tE7*7n7}7 ;7|7'7Y7p7es7aK77r7T727Do7!7)ݟ7Lb77hȓ7D7E77S^777 7I7k77o77M7"7X7677G]7詣7v7L7@777m8xa877>87c717U7V7k7-77P57R17c7V$7<777B7"88- 8@8;7o77?757n7(77777{F7 777r7{7H7.77}777:7777<7j7 7?7y`777R07K7NR7m7;UY7T7u7h7K87Ҟ747_7萉7ԓ7ѝ7w7m77X7_77=7z77>q7B7^Tf7Jq7:7[s727U7EA7ڂ7t7$7e777F7v7c7a7277,ٴ7yD7Q37x7i7r˞777: 7h7 7u7g7o7ў7717PЇ7'Y77u7Q7B6l~7D7 &7Z777Z87w77r71 7&7tШ7O:77eX7@7Il@7%=737'76O7je7577gU7'\}7ڏ7*5[7l77B7:7;[77qQ77Z7t7i7Ǫ|7ɽ7u7ن*7d7D7u7P-7hUQ7p`\7B7i7Q7͜79I77| 7fւ77nL7T67a7747f7:7c7J.7ty7$g7 7K.7i7M7ڊ7A7S79 7Dž7xB7]7h=,7[776/679,7?7ǎ?7o~D7{7 77P7(Hl7X¤7s7QG7{7{47(7-Ь75+77M7+6G7(6S6'@7.7as7CE7O7췋79W7̥77p7]@E7/k7a7U 7^n?786虊7.747X7yl747I7sK6ߍ7jt76877t7P7 7~7uL7 l27{A6^t 717ry7<7E7P7h7+}76yt7"h7Q7n¡76$7Ѓ72m7EJ7xg7 7&/D7:7~7*077S7d77;7y7+73E76<%7|6r7}7Y7H]7\7q_7^d77@5k65aG7RW6E66~6X7H7`6D7L5 7C7651Q7v6/777&6:75p.675[ 7kJ7xw6N<6 6I<|6:6 66A6n^6ӧ6z6X6B{6,4r6Z6z17"T7&5_h566b6>5[IOb5A5 ̇#r!ث656)=63747,6~Pns޵[w3<6G+O6rȰ6&TTm5 67ɶ61Q'{wہKʶ̶ WReIJ೿V>YA5,%Iĵ4@S5ζ61n;F@N {e1SG֔n^`GuǶsO2D.̶f04J*6U:'x x =~4LwCqu f-V|pʘiWǶ+Ķm>\Ưh5-3UǶ5ZǶT@6 ~2BK$9)6 -"6ⰶo_;fA܆D㸶 Qv,-H-r%cĚ5A2(^uRGɶ̶%6ex6`3$6w!" \6S[6 6J6d5N|D0UD{v}ftHD/?Tx жls,d (5ߩ_6N,9mͿÕ/6@94i}& \XVCK/;to򪓶1pr)a↑Y̵+'׶mw>ȶp28W6Ⴖ77X6%6Z5l"6)ju7CC 6Fq6z,b6IRp666 +60 56 V9۵g5 0ᖶS'765]6*6OO"5C+k6Ma6nM4067[)7V5E6{ 7Uh?[5P6!6Nq6>]61/s6Fl7"k6X6B6LT76g4 6, 6 4,7T56ً7 7ߕ6.a7o47U6=D707tC9\6? 6-4ֳ 57+EXmp7iN7:V79<7\q7LO7cy71ah706K7SC7.7i;7_7"7G66178j776QM776ng7]7C7F7j7*7z7G7%}7(7ౙ7¢77b77 37b7#ZX7-$F77"Oy7Q7.j776lO76]W7 -7$7 %7l77YP7Oq=7N7Fƣ7O>7d&79FN7:S7`6A7bt7jX7 79p7(x7F7|E7.a7E(i7?+7`7vZ 7zT7ʪ6.?76w6t7d$7+sY 778I5X97=,7a7}7"G73X^7u>7Km7ڋZ77%7G70+7_7YN726F6 76v6W626&?6V6"6J#7&E7,Z<76]7777j7.7OU7>r771<6E7[679 7I775\7*+b77W4787w7V{7<غ7Qο7H7$7 Q7F7eL7}777 c7#77C75737Y:7%08&7~7V7U.777^7$77v7_7ͷ7g75Ë7b7w7.7]7Sǡ757҇7A77\7d7737= 7>707͙77E7n7]&7쿏7w7衡7M K7V7$7G7b7g7Q7\7y7׍97͇7WѸ777B7p7D7k7ٜ7G6re7:5Ix7J7w7 y7bI7U7c7d7zG7as76O6\63\7p7_6;7`: 7C7&7O7171 7 e6`Q%7%6G5I7̍61'7B7)86֞6O46/ jxf6T6ǥ;?72 <26666877Ը7k6I&\4W 78y65n6d7y7~6rr69d56RG'"N G݁$Y6CCɵ86C6]6n6zF7S76;յ55 o6jޛ`JеJ⵸=>"6dѵXִ(+7x6Ūs76@B 7=47c07^)c7Y676/6*[Pފ66DN<7 h6((7m77;W6S576 7R7%U7ooS7B7"7fc6r666a6>_6'6=:+6K7zS7 I6Y~697'%77@7u77b{7I7Q7d77 a7g79 171 7 n:6y5}D6!:5ᇵ 7V6@Q517z296ȷ6k7`17!6~65*m7L7c^k6P4uO6#5Wk676+7s 6a05[6,r5#ڴ6EL6z56s7oT;5R_6r5,6G>7E0}lB7 76n666 7>76z+7 ϰ6&14L/h7 676A6F6s76667)7As6<7=5&7a7v6D7#7{I7s>7~I7ğ7?/77w=7x7%tt76pq76wv0A7,56G4@7ꌉ6s 7Κ7lS6<57O=7D77`<7.7g?57I7 6U7,6vY7K37 66!636^/6-P6[ X 6)G676yB6$K6R7_6ܦ5dp5646[E|77 5:66޺"7R}6Z% 7dN(6`$6RGyk`Dc637I5`h6-:6B|6(s6d6Ń?6 Q6t6^69#GG7mb7…977^g756%V6d7֣A`6^PyCMQ)Ķ6p 0ံ/7#86ٔ2642596b5q2C6W}4J67S59?QP1 ɨOW*I#\ՀC<Bٶ'x4hh6UP85VGԵ 5:\!^~BTci|#ȶ?yJ0>BC9Bf!iT32ҡh:0`sxh" +u2>I5r@Ƕw5]j`׹q4{5m 7t^ⶾrDd' ܶuNQ$GH55ߊ65yjWMa6d6Џ)5ĸ6Ȫ=9b6j7ɶ{++RC 6+D<] OGPb׭YgA"$ȶRMc퓛! 3,J@G@3,E<=6)Q(7#xU5)6?s6O3:Zz6l.BO ǪVap+6")45-0ځ6#66貄676;˵56[ߵٶ6֪Λ6;:5;V626m61j6 7ޥ6]5g7'<9Y6|K5k;P6K,Y51Z6=6"c2P w86A<6|5 0u66iG7l5H85%Y5I37H6L6n7pY77*/P77Ou77 N7f}7n7H777;7-7@{7^7cNJ7\*77y7 67t7 7H;77\7v7z7(7^ 77 8A7z77;'77n¿7|7Ѡ7 7o7uޛ776717o:8j77\177L7yM7ė77>7j>77S7T7er7z7<37YrU7* 7Jo77z݆7}7y7p77\7ݭ8|7{77ֆ717(67{i$7C!72271@7֓6*66h6277A7+U7/6`76gE6v69S6ŝ6K26,Ʋ5-dp7"466979q3:4Y6]76?6ZPk96\[s5a4)귊5ڗs UI510<}jg,6ǚaf4$53:ݶ,6E6JZ4G6Ɛ6I5* L3 ni#6"Vy**+ < #_ۓηpE~0~c`*4Ƶy~zzi6 K=5K)!>655HRݛiPNDuuY4d%U6CԵe@68`"jzOl*b`ga#Tk 6Te <&,eh%_p$+|2$̶l[ jo6d]nb>&j~Q5KF(eqeϤS&ika%S/8F]|T8ˊK(821ܚfk,6E7aLꕷ鷣`+tDⲷT>dlXJ[+hշv>$(䧷M: k6SS̷RܷWF/iʷéַ ԷҷEm ķᒷ(Ye4f$4y÷H2\,.4h[?0vq߷TtǷ:! >iJŷ8ܭaƈh ǷL6)틷Z[)ʷ1Ɗ5LiB?7Q *|𱃷тܷ"H߷p^ٷV7jU*`1sZ/7_Y1u#wrBѰuB/.2~Qy4J5ȇ~ꭷ[@yjXfu>}rCoqcKLh,UkUɷ\EIgm@y!1G巅a^Wr@>ķlZGo·NXn8pHŷ1Ƿv7)yD"Vb?€ ݷX䈷􃰷V_Ϸꂋޝ$ͷM87ȷ;mȷȜd퍷D}y ȷ$䲷h޷|@ާѷҷ4Rrַ3ӷ0h÷ bǷŁѷ}UƷZ|޷"gYķ2HYFet,ҷ>QQ ˷跑Vⷯ*ַHrݳ-!EmзCm) ط` Eƫ3}Ʒr LɷQ-<췲*ŷ޷ŷm޷_/!콷0~mķ:m`-u&]Ϸķ~zzAM򋖷f˷=y8ŷҽIʿ!ٹQPjLpqcx5ێ'PsdDmzd?B #ηf?ݷjH;:'폷g"Cdj 7>nіַbLs%S?\잷TႷmj vͷڷI`MĀ<炷g[7cȋ򎷥ȷ񱷆|<,MG~YٕeNzzXŷlMif⺂‰Dt]e{8~ʷ[hvէI+Kqȷ޿Ʒ넞׷$(oA&Yʵɷ&G.6;ZPj8=Tr3eh<vl%ܧQ÷JKͩc,6W6KOM7"7E'6M6~ 79d7P/7 7[26W^{7"I656ƣ5w62ѝ66c56b6o`66d^666Qt6 =5u6J#R6h:76lv6r5(7Ro6yA6ƈ47k6v +46gF~6MŶ6$686q576iv_7;.Z"76wo6,6z6[7!ѵ6P656]'eHr6X~۲5}.7,J^3o57A#6Ev.6> -6864 O7bC.7A#6+U6MR65$e75jO87D37I7%6J>7J7T6n6b6y63VB7UX6(ä66PHu6}O'䶐5z464B/6x666W76XH6"6'r5!O6۵3)25ڶ^42k55& {P:WߌO5"4ȗ^;c@1%F 15QΏ+q6664 8 жxֶs4 Р]dG:Štrp÷mܷDwn·D1yəPr9S\8÷9Z2 mڷ2sa\Dɒ5rƷL÷Ʒ{ ˈ÷)s엳 {÷:ҷo귙'jǷBټ昷ظEҷq M~q| ϷB<˷!K̷Y93VӚEys;By80) vN@ַ &;׷(R\ط#!aHZ^ZoϷc[÷ʷa+ҢŷbkG{lxܷWПrɷaԷ͑fɷ$η3· Hз+S۷뺚3'h-@vշm[Ϸ۷-mطMYa><ruŏ]myȷqJ3*3۷Y{bfηٷ;Sҷqh4ӷ앗C("Lom~c2(&?T2OWзJɷ}ͷp8ŷa쩷޷vƷb6౧!ͷ1ŷӮEʷ)s{ķu UҷٷiطN 4׷ݷ[ȷ٧BЇ=zl_67h* wyXٷ% Ak㹷0޷S˷YYf\fɅol9ݐsSη÷{-зڷogi깷XHi]$Y~ͷpŒm߷`›]ژͶ묰tBC" )ŶԃtŶd6lA'R/dsr)acUdu{+8?㗷1N5g|Ч[:f$r׽8ȴiҶ%BZ$[iz钶2Ykʶ [\E3Z0T NCsɽUxö+ֶضpMLS6F5sῶ춒z6LQ.f4E!DoO栜7n ;˶*k6BǶvH~_5 2šy=as/"~?B)\+9\ri˃otOiY6|j35I5{3<ֶT#*6dg#a:XOp'BWPAö'',weʶ_BA16(x53^n/jh^ڳȶvRK'.\m:J ;Oѻ$_9 ~yQUIA_563`H嶏6a㱶A) ~Zٶ-b䀷ށu(=$I7QlSc\ԶGR9+} 0kVr]'WB+ն4wﶈHiȣQ7ޠö iF;m! Q,:涶g/+^ ڵh5.ܟj)fѕS2K5R@#Hd6_ ߴ&\{o *A2Ҷ5T6{<$69 7M"I5`6.;5:67 63,7hwղ66t66166*4k96ꥎ6߹Os6)7J7 HV7e?4L76C6f]L7%77I7_7){&7d 7B6}5X]76P"6Ԇ47&6q7R66} 7B6.7#5_^27 7962`7Α7i}77!܍7LU7v[77xO\77O.U7O`\7-7B\7ŋ7/7&|66E7ұa757\65Z76D6$~7͈Q7Th7 !77>a7Z7L7"7׉7$N7R7N)7U797.٪7ϼ7vp797֙77>=7GQ77T;l777/7@77-7)47%ǖ7$D7Tss7=7'-7i647r47N<87oy7?7 Y7 7n7j7Z7%7N7S7UƐ777U7H07xΊ7>M7[f6K7D57Qv7ڈ7Al7͘7VӐ7%7 7;ri7;7S727<77?ݐ7K7Է7 Y7om767|S6δ@Z64t 7m,7A"7J7 47f7:\7#7?#7 6(}6%6&$765"67o7wp5J6_6K{6p7F96) 6tq6$37~6_/5y686O7E7Ȗ6+6|7V[6S!"5X[6Dg6&6Y)56ҟNͶ4 =H϶wKϵ9!񧶘5>} ~&+#lm|Ӷ05߰EtF^$E/A`ixsG#6^d"2)DL挷ѕ=J| (D[>ٶ6ض>f}X9!Jm"@ 111bpB9Rσ\6JZUɨ·vg\qY|JE; A>5FöՎ ݄#[0]0z8/Sl⓷2 `b׶G]/ w"B)(h f!PBw+ KlڶPP:v9ȶ昶^1K0!5L&5;E(>٭璶|A!6k6n䶎3i6#664]5fj1]^0ʶ]` 6VԶE5DmY56QЧ|ɘ\6U16 16 7t66ߵy7&pb/2`/ȭ¶;6p5﷡6̂_(5U 7n&_6HBp6΀Ƶ#53\e@I 6W 6!<76R<5bL7W-7"7!6ٓ6S6t6la36L55b<. ꡶ n4*57ߦ6 #7Q7]h7t7|6h\7wH\7!7JT7iNf6Y\7P666'66*?7=6Jר6I\7I6o7 7i776q?7á6] 6ݗ26V7@7U5,76LU66$6769o#65UӴ\6e 6Rl69 7n5;Q6P6?5L'784ӭ/6#?6G6 D5x6OJS62nv6߶6\7'h-7l7< 7c7ET@m6o5."{4OR6JoP66@76`6ԀB7g&7]676Z6r\77+766>6x6 6F6[66g7t6Q6^7OY77'`7/y7$7xm7)66C-7lC7Ms6(6b757r(76»>6P7}\6ON 7^#W7*u7hV6Cpk7>6 7a?7#7hN757@X7f7.73V%71H7Jⵑ0j6O5Ĵ2-6]+6 5m(7J7d66q67s787@6I7t6X7r76n77 6xr67J 6&/%[67Վ536ED7S707+7sP7^7rP7/k4M,7?M7(.7>247z9,7 6 R7 A66Ybl7!W7YT77k7o75׾7 .7J7׀77鿢7Йs717\+77O0 7$Ȅ77 7z:7 h*7-7Ś77߮77a[7պ7#;7֏77 7{ڍ7m6V 7s7k7.7v7zz7܎7r796(77W77 [6m7d7F8/7׀77T\6G797B77f7 75[_76bm_7 6}+7 7]77> 6h6pq77[X7\7>tL7jx76̬6/7$7)7翙7;b77n6C7Ҝ7^6.p7b;7 %7@v7**k7R7d.7F=77_7ּ7$7C7w7qQ7ӻ7!77s77XoZ7 ȣ7{h7@7g777k}7a7%77N7w77N 7Y7"G777`7707k7}y877d57 8W7R7z!810!88{8H 8$ 78V8V7^7>7 7U7%7~7A7Ø 8178877 8Y887:&87<787&77O87P777b7O.7Ԇ7(77f;7V77˅ 8778G7m7j7?7&]7-7K7`77o8L7\7u77q797q8d7ox737x77z_7:8dž8* 88~P8@77ߌ7$7v8u7G\77Z77vD7e77cB"8Y 8tR7Y7O7o7Ǝ7h7q7b|7L8i7L7777#7 -777 h77(77&7\7 8ve7r7̼777"707Tɺ7777+7a7x7ǫ7V7+7K77.7,Ѝ7j7߫7u'7[u7D87_77M17D7v776ޣ7m7JÑ797r77%Q~77n7x7n@7o78v78Dd87^7jI7~77,h76ҳ77ORh777p7y}7'6J7y@76B767(G7W 7(q7F?71^7XI76τ76(7RG7>`u7$667 ~^7A7H/X7؈&7}7(6`7]66,7b6"6R7R7#61G7707?G6ۂ17`6sU26ZM6X64g5G3U6~!]m+M^G6rZöx~i|Kj >fT65 ifFo>InORǶr쵒'W3z6$Y4dYK 65/ $5nq5<ŊG),(׶umeʶl喀s󶲰 5c6CP&m'a&lWM1ﶷIX',m!FryQԛV^uж"I9~;5uҶiX5W<5gHA-eݶ&y226s;faP*3=蝶'y߶X!s?'ܶĐ] =mL }LM!8sޡq_+C߶:zTv*'0PEB2z2mmô5f ~jA+@JI߶cUG,AㇷPxvwjEԶ==LbbU6Fs@+NQ \WxgC`U [Zlg=i,Rp-;"GmaCOutO`VsMESwb( l$#3|8ꬷq3Lp8g#ws׉In&eu·3Vg-g/2aAdl1ٶE+\p:D }'OD% 60Lgi<,-U n޵)9ɶq3Ͷ@^6 ,Qj4 Q5 8Y!Yx"l**NgC@Zߡ񺶤D6?5H7}|'7*"7q.66m637vn-7|6K7b4&D66X7[61-7K(7ӂ6{X7O665^+3"ʧRv6&6OĶ66-(777#76F663 ov o6+6i!37?6a6RN7ޱX666Aʹ>6L6G56C6$66O6b7e6Q-6T,F7y5"j6/7S 6/+"7kV5#J7Dt7"ʹ[6ﱶ5%5D?6Wa772F)g7P6/7| 6W7݌5;6:%6,4RkG76{7y76l7B %7b7E75$7&C76-7ƈS7n7G7a$7C77~[W73XQ7O 7Z7c~q717֕7?7_7-77DZ7‰7F6}B7D5ߕN7u!7zw7 7YXo777U7>h7F77ڤ7gЀ77nˁ7zD77u7% 70%7,7A'7+q7Ih7zD\7n7)7tr7 787 7'7FKh7X7*:7! 7772δ777,7$H77"7h7U77m7C77K7M71ɚ77l77)7:7:]7Z7ۑ7NZ777L;:707}ϣ7& 7#7镔7Ɇ7cj77|7й7 7777Ӏ7|7q77_M7 7׷7f77މt7T\7Q#7„7eҸ7~7a@77.7J\8[d7:+8q8.7 7P7ԫ77͘7v7^7"ˬ7P7=7?77'77h7K7噡77087.7(7x71t7[W77$7R7^77n777i7Ϗ7@77)7777|7ň7̄77 77!V77e7c7J7+$6w7. 7o7Y7<7 <7_7K7t7 p7A7!7j7ፅ7qK7K77C*7*\7|i7)Hy76*77u6H7&7w7F7}7|'7~ɔ7707\7d7I[7ͩ7Fe7=7#7e77R7q75`7C7777s77~7`R77~7f777 Z7e77˭77^r7727 27X7BF7ʓ7)7PT777r77 777CPx7"7s7N7,.7ow7 &7ɳ_7Y)737DŽ7T 7)7E7#7Stq7=P|7:j7C77l~7so7{I$7L4Q7c77h*665bz7=677*6B666M6Ս7w6;|7,7酑7777'ٔ7}7i7A7k7y6)r27@T7%76567|Wb737yY7^77A7_l7S_767t7}'7VȞ7do7q76H77B7g7.7&7^6h`7b578g7fk7$K7̇7tD7v768e7C7-7W7*M6x7NY7C7h赔&7B66X6 K7yWh77RQ7;7P75Y7d6W7^a7,6r*7ؗ6k6J6% 7)ѵi647O^5fo5p5k626o7 6g67o627mE 79i6167jq}7:[5:FhYb6N3Qs"D^|JB&7o26<6#W56]70%7HC6M 7{6z{6$=i95#f~6Pv̊`6/6 {6GM7XE6)7={6860 7ע6 6V\6֋6]21΢6AhV5> 5EX5R?5U_6,'7006_7>5nN6oy6l˵V;6aEJ6c5CR#Ķ>L򥶼j// Vd0}6ݶյ(cl(55P4 #k0f[̋_ iM?2aB ea %Lsґw6/!\+6<*H '9့% =H$ivno -:^b2 >V<Ġ7]Ѷ¼Ѽ,Aط K%JEݷ 9D̷]ռ+dv겷t$0 }Ba(XۛUics׷j޷6Ҏ~ƷGs+Ϸ ķ^ȷַ3շw\ķRܷڷJ CrȷP Ƽ%(0շJ JZ ZܷM䵷=2eܷA˹A%ϷH(䚷G<ɷM< >Aз5Ϸiշ зէphܦʷ몧j8oٷHηIt ܷ4&޷ķ.LH T[P&~#_jA[7[Z÷HUސϷI$ٷXKַJ߷[!I˷nطꢷSkzQɷjNn Ԧr!Sɷ0YAo߶t8IZyi^xGU28%yM\_%߂F+ҲC?DiFB 获hO#]3 j"Hܶ:L KжQ㫶!Ln/%z.l_mVsG譶>1件yD9쵌(Znȵ_1)* JxajѶhֶqk0w&2mȑ 蹉f}y涯Z|5E{ܶa66IZM Ѷ !r@{j͌FѶ1Z6(R= :Z! 鶦틶i5n±j6Wk7`C=^60Hz4KOy15B66v~D{*8n8ӶҶ#4>6I 6bf˴6V*6ca56(6:-r5|:(7Jf7t]6g:67665 77 M75mn6: 63G7M697r7d7/fR7j7F7y7B67*j6&v6S67B77oD75U717HR@7!7Hg7F7y7 Y+7{z7<77`m^7ܧ*7C7 M)7yh7-t7r`7%7ϰ7?6D6(787(57[7T7 7U7;7O7`L7,_7V7M:7 777j77ӈ7%7*7w77 7v7 77Ly7E7)7X7l7)7y7-t7y7k7L7ۉ7O7x7U7^77o7%ɏ7F77 4707q8Ĉ7\7Dܞ7ɽ7)77897)7u7ֲ77GE7ߏ7O6Y7ث7I7 7#M7pۣ777uUE77XZ7͝7777A777(s7w7S7Y7\7Zq7h7c7)7?Y7$Y7SJ7A75O7;7̖;77`7l7/7a7!ߥ777z7)17.7<6S07x7U77G7M77l7-77a6h7)7w7'7n7Rar7DKK77q7d7Ξ7r]7I7֢7'977797J7Υ7z{7Dw7k!s77f7/7-7"n7W7.17"7e7O77`7/7767f6[D777 7d7~.P77g7x77wQ777]7bq7-b7Q27O}7v7Oj7=271}76p7/7Q7$ 76H5ۿ7j+797ym7i7hv7>707I7<77 c7&|78}7g7#57[7/7WK7K7H2<7(6ԑ7Ǽ6JS7H7z6ч7L@6أc7r77677F767y(7 "76C6)786!y7N&72O[7'H7D65u787:77/$7 '76\7z77 76]7w7f6{6^6%(67{6W6X6>{W7u6v6"7aw7qg7f7Y>7D67569p6x6E66E6 }67(6? 6q.6z$76+66 6:Ci67"+666}c 6Y566U7֑5 76.17h6l\6 ]76ש6;7< 7465W66@\6 s5~7|7\T6Q5U65b96=6̑67Az6P"7f7)7(7K*727r6n$76v 6{5a6yZ6kkf_']cM󶽺=sQ x4\6F_6P-`P6o6Vm6"&H37 7Z586)6&6 T5ƛz"5p=}g#k=6Qw6I,CA5j›lFP8b4}5>LC6)6nII`]7}E"<B0Q5꒶86GK7g)Lwu54rVC'STD׶j5y<4"B*rS݄=ʶP~iJ5`-x,в?-PAq\7GJ,jIv643u s]n4)N }t0\ ! #b 8Pdcb }Z̤h ΒU;,|RXjg6+%ж9,ʶplQlEe/ľ`>Sa2wmڅ[@qԜѝey慷ITq􃜷r}bz÷*VbϷ05إ&,TC?Ʒ<$*"5)u=_ꄷxlAeBoҍ.KGݷo3nзuQ﫷ҷIz|攷O9 %÷s9護N`xɶcɷ]>lBDŷ )X~ ̷"ypV`nz˷K~۷}(l\^skVm˷ÜoHUqO`1(6VB$k,·bZ=̷ %+ƕrgѦU̷`X6cշgӷedL㜷0DsMS{[רXϧMCPg׷b Q=Iշ_淲%_+Hҷ!jp()߬"uoIuÉCKlM<ZdǷxY\πrLM\FFP-pHz: k h(h-₷qet*ж:C|"j[u jbƶZQdsXvOjB붡jf܅[Y퀷;Q\G<̛aZ:Y n͟܏9@B:5^*K~/yuM|Ϳ>wJp1*.P$öv]|eÞ.:t9g!Pz6NԴ϶\ ජOλ Y.4xQ a`P>᯶[*!C5wb=7VcɊ Ѷ$Ӷ?d,t5YK-({/3qN 4EŶS4m7<96>O6`>06R6%v6{6b7晵zO6R4555{k5s6:I6{676F5/kS.7777}R6mL7Jq7V6h57:797ƻ6Z"77nH{7666yՉ6Ջ%7=}[7?6[t7 =75 7D7S6!7v6"W976(7+6 C7  7x6*v7%_7D65Ƀ7c6ˇ7407"`*7mH77:S7uV77z7j7G|7767P77)76F 7|D7i;6~d6$6[67V6M7]76ܹ66D767>7C^7r7>7Kk7κ777,78cO7{14}76=7 b6w77,G6Nu76]7/N7y67bT7h7'a\7t1#7k7&6G667q67p6T6o566=?76DZz7Zv7{.7=O7^ 7ZS7sT76 673J6<26546J6Sfh6|)D5H <6Zu5u67g26t@7P /7i7 6+7־7-6&7B+64 P< ShLMk8QzP"kSЦͬ56 g6Z6h6t6KƓ6O6Fq V;6n4C4ѵ56t7sn4 6 5(65h6e 7X6޴.76;o7+6` 5IF<%F76Z3R7G7:7,"7z6[7K^7EŃ5"6j66(6#97>u7p7x7..7$6\7 {m7?´6MJ757P7D57'6U<7VI6R6%=655)0774I7E7d76a7}I75E7ȷC76[_6R(65K6 7׃5Q7*͉6)^6%7c5o-66M54 6f˒46|5]$Ӗf83>66@pT6`j.rf66cP ʶ#,~9j0KRG6 YӶ&/57Mfvp^ ,#zٶ=--C? 7f]G6C.m!:`;k*`.:$~0Cz`g]Ӑɼۣ`ngy÷X缷Ӆ>6MAiwS@኷ ^l}=VV!·M:4!O ƃ$KMI/Է<឴Lu6S"LWQշT请衉o(iBuƷȫvгaҷ=) \J>Z4;vb`HhqyL4|64fF϶qG'= b-Ֆ'yH\ao"qB(?@^Jr@)jdO^🭷칷;o۷ ٷLK৷⻷DWѶس[g˷ѷe"ȷ2շgMq跂,з|l }0ӷ%IiŷYcKtb/k.`DKʷܷ?0ȷ]d#tC'*η)ַ6Ʒ ķvrҷ-·D}fT]k5Lp ÷~ p0V}"2p 48_[NؗrJPηw:׏ZV{4'v@ds!yzX4)%-4GU<`'QϵP6ש&{KK.\f/iN= TεiܶF3gc=@4.{@"/gm*kItms96?ƶ5N^EZѶ϶cAmH>_Ƕ $ދ^NgO6!穵u6W5^w5m6g"5߸6%4:66.V6~슶56A6߱)5+Q[|7 saр5n66 6 46}:67056Eq56!uw6Jx7R3e6SK7R@7/p6:_64557V5'7K6iT6J 6 76_#7q6k,<7?67(77Kh_75l7 6T7&7r36!7γ6>6u7?{6"6Շ6 7YS5$7w7v6]77Qs 7rQ7T,|7'c7|6`[7c;77%7f.b7a7C-7Ȥ74pd7l7$r77`N776`373OL7"x7a16a^6u 7V}7U79F7 q77l7ă7X$7 7./71_7.^77s7Y77Ӧ77777dŒ777L 77647G7rP7]7U7Y797 v777Uf7H7L7787x7yE7GS7777k7k77V7d^7QQ7aߎ7ͩ7*7v7 67s}77 7D7717_7Ws75^77ָ8h777iU7{7&77\C7͏7oV75s-73v7L7iRg7+56j47pPK7Kj)7c85<77667D66 5 N6*6t7P5Y*76`7'6 6m7b6TN$.6176,)NTP}=UJ)"{6{.6ù%6.A6$m7f7\71/7A6N74G6s 7a K6Q6;U$5k6W 7y6ώ47*4r$7d6Y6UH66@״ayz7T6+6m 5繈?56ZeЙl5u86)/5yv6c|HT"6ԶDzu5t5׶;8~4+6|5iIy1iD@j|aox<\5H < #fж/CĶXöe?PR35_"Q kfs3>Q5u"RƶNpF2[YdXRF"s&(|,W:dlʷ; }tz͖hPRbÄvLq+7G#Rbk#SXZEHm÷!AC$c[?H"z>dަ`c5슷dv÷YqӷX˷Aŷrطɷ:쯷1O ŷssq4LRVŷtŌ8󷍓U rBC j掷~;1@·Ǎ,Xie]_~+俥 ӶMpC( ̅Ç ݧ͵N`A1f4An^ q\#uyO.c.S I(!䩷%ηط ءX'UYH@VinE<=f NDDbͶ9=ڶӛ tXP`ib`֕AV1Ū(q[ň&21 (\M͖f!Ga"%o۶2,*p}e>ˀtJ׵akY; 'TӗVI4ة r? g>BM2-^?E0ȶg ޶h3H+on'ѷ?n^`ϱr4i6zMKoR_E#궣mI%ks.#ũtR&g }¦^~RAMԶ r-k W96dd @7-A7=777z7|77m77m78M7g7{7q7^E77%(77U^7%N7$7U78777Z7wׅ7%73:7{7e%77|7V7o7f7$7U71~a7Z7]7j7 7@p7}7l7"67Q7֘7-7f7C717N767J7æe7e$7I6i>7S6w5j6 76766h7Ӊ76emO7Af7R;6 I7,6n6%6}4hB7T763(7QG7-J7W7FL7k7/62747R7#67fE7re7/7d&7o"7Z7:6N6y6P67aͿ6B5u{7Td6t/$7Y7~6Ob7477Q67RU7j6ADH7 7WI7eS7@L765s7Z6`6Q7{7KN6N7K7‰63enF6J4z66zl7gA7!)787ҧ77#Wj7Sx76˙6 7U6Gl7T665' 7`6 6TK86 mD+785L7B6J6n7O 6o6 7Q7g7^z6B6Dx66k5ķV65dt>526@J6Ȏ6w47N66^2 7566C6dƹrӵ}r6E񪻶?4 fp&N:6ֶb]!}w`dx1S65N ߦɵ+.Qv̄Q`i/ȨW H/9+նn;˞&$% :cͶb,3ƶ 96I´^ =(;`2Ͷ켶ĶMse,匵` i&ŵt5r6xl/7# 6IZ&n64 N]]6k96R[56Ϸ+6s6Ym64<76J6t6D84ŒI6%7G*7M 5/7q6*60!7: 6:7m!77m;07[7/`7g7H7[757d$7P73;U7:77e6/6.7 67yT7W7-Z7_6 h76.7R>7>737^[@7ʒa7mJ78K7^ 7h767J7؇7 I7ssb6W77vd77GYg7h7U'7H{7w7(d7 7E77aZ7>~&737;7E97r7$7^6lvY7V76~6|5~7"-6y%e764FI77l7X77j6j6I6E]<6@<6s^7&R76zu7067Y7ߕ77yV7Ma+7a6e7G6H47U4)t!756*m7#5с7Bg68P7&7C6?7\6 6Ͱ6=h65ʷ6"07A76 7l~6!7G:6)75 6&9>7]6pz6 767Ij7o7Ӻ6(^C7؄76@7Y177,J7 7 7m6|7n46%6: T59%7m7]S7`6CZT775 7Ҟm7 7Eq7[579c7UK7jd7:D7)}7%WE7)7@6497!87Q177N37y77[7ٙj787w78767w7>7U7Ó#7.g7ؙ7ܥ7x7E77K;7v475h7D7 7,7Ԕ77ȵ7lv7SR77777Ė77[7W7C:7|VP7}=7|?7߃7h7cR77K77k7Z77C7&7=07?7E7Q7;77b7 7%79(d7:g767 7㗆7E747dJ7"77jY7,73X6}7(7 737Á7;L797{=77γ6c!B7747%n777hHP77u.73V%7(67*7,)77Cjz7C7'C7z6=i7(s7;ݱ6+76g7s](7& 6D79"787;Q77%76K7\{77z\70Ms7-\V7e7]>7w7.7s7A6P77f7.7627Υ7a7E7777t77`U7l5727wf77m7S77Ep76ĭ7777T4777F[7Q77S7Q77^<7ˆ7wӉ7777771Z7c7[7#79777c-7/7dK7Y7z"777\77P7857b7OW7u77xi777 7Rg7677wp7358&7Sf77AV7۷7H7]B7+777"777v7x7}U777/P77/)7∿7Pq7D77m7&77x7777Sm7r78:7V:7͛R7%n7u)7ֆr7!&7Ɓ7A7)7>7b7x7 777?'7pЭ77zt7 f7 'n77-7&|7)7X7\>7$7=7c.777Ê7(t7G78/7X7R7fV7Olu7(s78X7F777n777fȱ77=7t7JI7&7J7 777177pO7E77A7Q7b7t77m\7>77>R7*7ӥ77w7<7Z7O77}7-2757e77D 8)8Z7*7E797bY7"7C7,C7}m7tƒ7ش7Oi7}_7d7G77Nz7Gk7,`7GB7ҙ7S7(7=7'7\J7h77o7<}7cRo77XG7S7/^7i776f6O7`6Ⱥ!79 7ބ7l7RR72qg7J|7Bo7L.6id,7{M77:6657(U]7,9w7}70d7T7B7jz6]G7xe,7] {7 6'п6,kB76N6q65w57I6\6m!7-t7h7]7l76NA7x`77jiz7-5ˁT766! 776m6Bt̵6OZ7۶56F+6H7u%6N`715L6o 5!(6{6݌4.I Y K[W5Ke6= 7!6ض4厔V\|5ε;6yhAҶI6E.( 3셶V6gf|˵[ HOcm6Z5 PbK6_V6ڶNζ&Md6=/,93sVG˵ L悶h, &ދ0nFO|5pӁ~>SBU9T? >D~-B 7,y6 6n3-$o,D &;',EO굴=_& vTGmXA9;OB1&z!狷u+J&R}A5SP_. =|_|p0޻º{&h)ҙTQ/ǜﴷ)#X얷 RN!㖷粀U׷. ̷bly{!*d·d>F\@>QطI֥R$߷*/ѷd(pUQշvXaACL(}E6P6`ZZ59@I76^Dx686͔N5_6P4u赈6ܵ@߻ȵhDej7)C5 77f5Zz2bC6}!65>x6z#66 65Ne668C+6f"N-[:6 37`6t6rl7z)66)6-?6g67Ek6ԧ}7+6@˻566JS6ں6tP6p6C7a6~6Q(x5E7H'687M756E6]7`^P6ͺ567154+6r۔65%-A7ӻ:6*47D67m7H6}!767xo6ɮP7n6a27@50C6]6756D 6X(6kg56A6.6 7m6666H6Ub5=5S7U_6.w6 >07 76~6567 7V7:X67$Uk6'*7M6ЏH7T6HIj6 a7=T7i6g%667[665f7z6HE6g]7t<76Q7\7 667">7c#7j6t6%56 7Q615H06iѶ7B'6>7D%662=7¢6.v7ϵBV7z7{5*70)4{65e64^$7~z8܋5Q7\նp*6 \65 & 7E F56Bw6m8;7w뵆(7d7[~6"i7!6˝U7N6s=6zM5g63(17uW5n6k|6WpH7r977c6K6B=7K.v7Ђ6c6W6=ح6751975CĴ3I7666C66606f7,68373c7D_$77W67666K6)66⶗&W6{}e5_|7SE87ot7f7ư786VS6M7~6CB766]6T7A N 6ĩ $6,Il65p6ւ'706i@7.7~26)_6eT#o6*6W6m/p6"ܶl%h6L< (6=!ǓEE<6z66u6 Y7l6dž76S646D6Q5j6 6{6#@5cT766Jo 7W5W7oJ6K7jh6'37X66\6{7Qh7(-7R7M 676x7>6a6!7C6Q76Ci7}s7(37F7T 7[XN7ގ6c2'7ll6"?7O7i25667377J7~*7h6&7C`7 |+6'm76A<7(7O"7N7pnȃ7}_7D6A5D6΅47Z76¶W76֩6C6ӶDg4716mY=6! 75Z5) 7j6B65 7 7T:7R7Q777oL7$767u|6v550{66AD6p7\4+7;\7/'7`7eM7L8G5:c77sC6&7L 6 A7u7a7Si74?6X:7g6686z675rE66[>6B6 dw5+5']7a5J6ȏ67k59D6Nn6m[7\ 4ʾ6@66n64>6G%6&7Za67'*5S_',7_~]66 65xζLt͢ C G/ɶHc?˵%/6z# Ѭ6߶}ߕ68/8k=6lIG7qVس6#/4C]5Oݔb@׶o+M ̃ҵ"i3zId۶lȐc tE55I36ɷqҶNEfUضCR54.#O@\޶r4v"}䶦?#J6V!z;/ANVTh˶zFWDF;&"Iiveϵefp?V{LZe)CGөj:NV':{[qƺNYÏ'J wC0Ե,0:Sܢ9QTdZv֫+ȶ߶EQ c'}H25~K0U瘶e=I$#e޶@mixToH{EwqAkq[V\"uxԶ>/ßh !ﶯ~5J`W%*c0 o[=WLзʯ b/9Vre I.cs"2TO>·=߷SeYE-}VǷEϷ*#MM㒷WmZu ;@_QƒLmM8cc󲷷:غ6#Pde".ǷE Oy)L󟹷1 | cٷLַ !ѷjza۷ ~Eķ㠷qŷs·DM즷{d·ģÖ_;-Vt߭e. Kְ@n"_a̷fҹ^웷9ea\2ķD23ԘHDH ߼ތ:D=0d뭷?C`{06/w0(@%CU bO3"񼀷HTR%uN NnѶ<-&?3>Z pAS`c6϶BW5S6B"w+Ķj¶{s66U\5昶4T oQ,5dѶn{g9وg%L5:Ix ;t366WY76ܡ2:y56IM6Y4j164{05:4A6"j&A6CQnh_\ϐ;o*7._6nyN7|?7`6_76頴إXɶGve"R>h*붥I?Զ߶2;綀5az5H6 67ɩ73Uz6#d`IӛȨȶ!ɔ#ܶ(Y5LͶ"BRx(dhAC̈04v(s޵ӭ6Z27 565&cP;Oc6ތ3Z666J7SK6,7Aw1PDl6~ٶl6͕I2ܣJI[ -&d궺pgs?6)B&7"S7W6)O776G&7-F5 6QpF4|6 c6S6$16Ⱦ6 |Ӥ6T0666[Q6X7b7[2GL666qcPB7ں06v4@46s6 6 ƙ6 5!C5626ʶ5=6ł8*6P6t.ث69HԿ 665%/6H5/OԶGX7_;7, 5 6"{6o#7Ǵ:fP4۶ I6Tn6U6&6%765f 0D5453@P«5ř6'c ?5(X2o g52oBJv{Glٶ3Ķ6ٶ⠷_1#ɶhӹܚ6=Ƀ5 T1^5#qpĶB;?5rɶ3 :)FPqM!J(Ӥ]SF5(R2Ŷ^r,1} ahĶWζ\XEj~l2;,.ϩT(,bIK2GA6Ut8_ݼrl;&m`oж۫46N6>fx@OUq44ޖa6y`=;[Qv*ն4⯑ln*:cə!+6]^5, 7 艶6O^6h6l746jF66V啛4S ƶ}*7SF/6$7 tT Ͷxz3AIprYU/Pz'·4%qjTnBIq~÷(=ķ(,tϷ@Rˊk>LBCDHz1=4н/aLFX0F+\'a=Fɷ‡yϷz?;(Qfٶ=9/w41M"4VQF'|'Gٶ9:cۿ1a?r>vs(HQu9̷mH퍷1ZŷG}yG-~lX9(rڶlOpbCh>0^LS Xٍͷ"߇]÷Ƿ锘TeR+9z7 ŷ)۪4}੷JrFAQŷEb j @ش]LzCY*ҝk&Hǒ~'᷊SrbAtwjm X@Pm݇vQ:dn5ʶ2ڕhzݔ(u;dDR5cvtUYæYŷݢCctNL?)d>Ja(O5fKP~9ݳD"'zَ/%G4D8 D}w07HHd ƶ> T240{qbOXVYQi$uy۶09eʶlV^*=\5ѵRkW?MK7Ưc)翄椦X3 ( /.${4Q!Ld4=5)<ϰ+H42R06#6s47)7N57y6='6敶󖞵6l{a6%5y:VQy67l 6~=7687s46i66S7:678r67ܨ6?)7,65> 6)s=B5z~\7-6uj7]6G6t$7mE77:E6TS7[5A6+646w'6yB66B.P7Tb?7iĶ~7%6"7,k6]N(6p6&ļ6<7c6=i6/7w?5r56ڲ7[7?6˝6Ǥ6+6}5f5j?6eQ6r*5QY35f5{*,6p'Y7q4p6F6*517+71 66’6Cj6[ 7N,@$6 5|56J6EB6B6L6 6h"6Q#$7[=7L6@757O-7{7u6lO6=7dW믶6 O+k/%4$i6~m%6\7r67E7Z77616:656I6=:6J660,7ޣ6;u6@S6FK6k87M6Lv7]6֙6QWL7UŶ6#j6X/76G75J37A76F76N 78@7y6F6!7466O]7ٙ6>665 6i5)74gD6667[7H77SA37{70O7b6&7^J5TG6MA6'6s6n5 6dT7y6ƚ6#6ª,7ϒ6D;6x׵Y#6Y77V t7x5B7s6@c6s(r Դ K 7`)7WBzؤ6ܞ5=-6֚5 7P)7f2= j6Q6;66p6*$7!6~66z 7ŏ]7t]JB66,Ĺȝ5|DO“5@lbc=h5(626.7W66yX)65'6mɣ67Ki4Hz6 KPd6F鶐)6965DW!7i#?6IY6G5 J6i5 |)ٞ{ŅmJ66/G[ V(f :3CPKRqlgt \ȶRV17T޶58$whԘZxV1aep4U1+/DFI4t%ib(c5DaC$]z~W&x/E bembV;#0MJx FF&P)k(?Q͛K޶z[+'ؙ3 B~mb Ž#Fc$ȷ-t` *^;U:0GZ..DUs ^㛷Egw'Nu*[M&m>zN|n"bR~}mQ;ڷщ/PI·$YyE11KR0Fnrh+[a/#koM|Eʙ~9|sIb7 IeMض8򳷖GO@mj^ceqK@-)'-}fq.J=Q8;dwpZu&EC]^⑷7XΈ»\q Kaɉ-(r]:(nc/Oc]o}V_4Dav&zqWV>Lֶ붼 ec6%4f雵 g@q:)XmO5Z+h3g57W d5 H4Ѵ+ĶP3z[6LH8656L6C6X`y7hQ$7W/7z7\6m6Q4L6,5Gvf7^.2^Q{D6Gc(507p6y 6}v7f7Ge7NP7%7"H74}6u7M$"7N6Bt6tT6b%6>b675J46k7M7^7~$7X77k[7|7ɉ{7u7767 7á6앝6j3797v6~<7fb6I@7MbO7$<7 d7PW7+7j7Ԗ7H-77q7_7v77U 77ɲ_7\67=k47[2=787277ݍ77ƪ7Z7W7d7s*7f}7Y787Vh7!7~77777Y^7c77%a77^7/8d7Z7&7\7ѯ7 7t7*{7ޟ77p77#7k7k77Vſ7Y}7c7X177۷7I77W 8b767 *7s)7E77T7j7]7Sx7}7gV7,7@v7G7;v7s7{77&\7i7|t7s77=7 7O7 &7gנ77 7\7Q7d7ܳ7t7b7A7>6 N7 7p 7?o7%7`72yL7ŷ767PbJ77Q7l7%7{!7+7p7 J6Cq7z7ʅw7d7ce79 ;7N 7L7 7ƉM77=7U=77 77a7]7?6Ex77&7Y7EC7o_6+7660~7?6Ƚa7AĦ6J66746TT7 sv7Q7S9_72~7`&7e&7}Q7/7 6z7(6z7A7+7!lA76|6"y6 е 6!P?7j6ۤ7w6<ˡ5N'72.6#<7(6&7v7 7S6\H6&66[-6ѿ6鳴6nO-6oV75÷6_ DQ6Ұ6R 7)77O665–6()6!`B!6J566 6Y6 7l 7FH7(47}B7D6,7YN 7 75ݥ(t+A6+52 r- ,wsMm65v66)6c6O,6紵m_<_O>۶烷d^5:B4?ö;:'p0 phEPuT%Sgkk2~u`E,%DaxAqUҰDlns {wbO4]˹!N3@v;{$Q_c'nG =;o$>"tFҶl|MtRbuiʶ8Vd !Bo2ʶ󏷭'eK@afrF$} r5m$>ǻֶJǘтW35dlȴ-x& Mז5$5I& P7:}$Ų*ߨ5Ңz`z`/g.KjMO?tI4ߜeUKʶKն'%\4S,6]4m rL66`& <=% ڛ6utB%/55l7PFõ?n5`HKGkߙ0(ʶ]|,6 ›4_ݑ׵3.6\S5 5Λ6{oʰyGz ]slg?bɷRVh*dO9גMU㶰hPHF|i)OPֶWy-`Z|= Q6pضgzes_^aBfvjٷz7)mjvcG1~me =}[׶LC=]ҶP}"'QLL%>pQaz]GK7jJL?|=RsFi{ \Dmd(6`j$`v;9 A6ū.3v6QwƳ','=|-wQn&Ƕ=i?'Dz&[f$6ܶBv N$"[-1"صǶc+9T5aruH|U/3B*ȶ E Xʩ>ة*5y7gʵQ4\OصJ6+q/)>#AIZ:]S:,-c3V*x6qgW۶ ~ +{s}Ēy#N>  +A}@j}r&4vSԜK4"\۞\5@_L]BPlkBY]N w۶=R?t5,GD526%Dlz64eR6Eei"U,)};ʔ+Z4SxU:hck+Y D%efZ mÝ)YFI v0o5O D@F ŶdUıWC4UF, 6 9?>Y"D<\6=&߶;ҶE \w74iƶZ>KX}3ޛi>@eŶٶuA^>yԵm_MmA`90_;궢,5+M6O6ǵ浗6R5(5`x05R6A?R7MVo93YrK2562e+174U6,׵$u6Fx6&86}6Ru6,J6/նi7@/.ޜ5m +_G U+676zK6Y}74vi7:6V:5P.7۵666]6S7 d5g6IN6Pl6^6Ɯ+Sh76s67B!VQ7366R64] 676773! P7v6M(7o^l76mW|7d6VZZ7ir6M7y7;A77"I7oI7`7f/7786:77)766 7m=7B77Y7V74b7x7>_77E7u7Ǚ7c7Xs7Hz77ϋ7 7\7}17k7 %`77h7mr7Qo7dF777757Oβ7k[7"7l]7b7i7D7V7Q@!7%7777gu7\u7]7)7k7b7M7]7Z7{]7K73777^c777b7Yҳ7q7g7E7 7Y7p78Q7Kd7777(Ң7s7gw7Y77|R777i7ե77s7ڢ7w7*ڝ777`n778F7^77Iݩ77k7 7j7k77n#777֧77n̒77%7 7Y77H77>777e7l^777y797cm77y777l77X7Q77n7[7x7'f7*6}7}7͏7; 737ճ7+7Qn7]7 7 Og7Z07 7t7\^7U7#O7Fh7S7h6?7,7$j6<67b7c7Α7F7Ph707737^7s7̴7{777l7 #7W7677*|7 7$37R7Zg7'LO7+sZ7 w7yٺ7>7.{7$7?;L7j7xU7s7|x777/7A7ٿ7qܙ777&R7p}7 7Ɛ7Z7$7S}7EΏ7H77r)77&7n7!7o7ܰ72K7i7o7477a777V7&7l7ca 7}7\[7Bl7_7K7y47y7c7[N7b76P76u7$W7J7'47| 7W(R7497%r07A-767|7l"6a7hy7J7\7E^7M7{ED76$|7*76@j7-%4777h6NJ7:v6ߍ56Z66"?6fc7"47Qm7 Nd7A-7 6k 07%W66ȼ6cf5|45iJ7626e6b57!B6fZ+76!'6. 6zk557'&7si6+6#5^6#6Gkzq ܥQn3J7r;7q6\6iR5-786k)a46k7?7Q6_o6m6^kg ڎ6:6Nٶ f6R67;7467ޢ56d׶ f5 v3C:G4%I61&6[6`ص75|gl4W66y6s6Z\65C7džxK6K5o쩵[ir9i*5j ^z VE$'6$4 8۵r6ur7I9 6Ķ"㵺9䶕=Wm%l;/]RXtR}fIg2{P/趮.ai kIz 59 a6&X_6M̶yٞ=.{&{Ep;mU+6׶fxյl6ȫra6kH4)ck@6j666P˶556%/ptA6 65Vˌ6y6@7H,O 6p546D2n6<6_0J-6v6@6}[6Ø6k6S7^6? 6h57 7 7jq6后5ҍzЂF۵dwN4q&76A 6 6X'7Zݎ6z^6W/7.7M6"&7R7Id6#G7Ra6=6W6ĕ4`5^5 DDi!5Fx;556-7w5l26GЧ66ryT5707T6 j7;5D޶z2s5޽QWb@6\6 6w6Q2gʣu6{MI6V6 ˶"\ɡ5Q9ZH߲U6lז յR~*O66#5Ƣb5B/5O6zf6̂KңO5 cUg%uնwTն6(Z6F$!>B4rɵA5L.6`KJU6l7(57A旴-4V'rP> 5y◇m76YHp5C 4%N>01HQ6/uِM/y94Ki,I0Q̶9=:Kն\56"(B6rڶ>/}+5s򍏶0pFg?1,6*)6Pv6%I263+SH/±R2+,ݘb}6-\.W6f 6Iai6X?C5 5.66OtF5{6g[c6+v5T7`n_6@6)׃`Sc ޶[tT6lf6[릵6Z϶WMM5+6;₶N6 6e07V6l%6e7v:ڮ6hC 6Fb 絗Ӎb붇ӷV=2y>5]9wK6y5x[6J(61?76p5b(6@c6Nض(E$&6ۭT6Cї6dT 6n- 65N E6V6'6azt5D 6cQ6SL 6kJ,ֶ845S6Myǂ5w,6`6.06/6ݴ&7N6U377E67Џ7ڮ6 7Z/ҵ65 667eG6s7^w6)7Ί7;U6%:77~@7/76}D7Îb7U7]h7+9757N97777_z7/>574 ]{7d?a57167$6p 7~5;G6767z7́7!ڭ7{57@7ۮ7576N77+77#X7w7w7B7uR767nf7 w7w7?7V7Yj7oe7{T7j7(7L7AC7A 7X7+@757J7 f76S7 r7.W77iQ77̄7Q7W57Ѩ7^g*7?7c7!67[7&7!6BO7ѭ6M6DaH7gs]6u!7h7-7k87V7i7t>77v7`?7l6]R6C7v6 7T/7OT6l}7ᱞ6yӵ6`B7w&K74J6O7T7s77a7-7757k7:^7o)766=710u76/62kL77m477s76*7NjB7W}l6l7)@W7#7$B7fY7>l7tЖ7v7o7M 7Qx7S$7Ư6Q47, 7x7z6=7?V6h#7w7gdB7K7o5q47&7 5M5n97M6-_7lЮ7P671:7ǚ7\Ma7͊7:J7N6|:V7h7:f7?7/S7f7!7iX7[U^7UJ7G#7b37,*>7U7[7]6,R7sO7'6676}7L7ȉ&7 7d6p66Y)766)\7FJ6?D7|T79'647N+7T 7,66LVݮ6 õ=[4"6n`m6pbxcn%63Z6)@E65냬5o;߄608Ƕj>"6 [ K"¿q^=Q`~ 8+\/Lh*ؔ6",l浺PnX˖{쵵&pu,SBeA'-NMC6(=Lks`76fJ{clXtB!Y-GYa.G,Tu6\,b[6`*JnP%I.j3(0Ԟ*t,#O#P9{3dpHqI~bdն "<ҍ>Oaau4}Y!x0p:\ȶ>: Meµ:5C6Ю5ڱ2I~K':nk8MͶuc|$%+{6!O!4ٶ"I4$"+6嶫j6]xփ54]f](=W Qs󶿥 P Q{4K6iö5޳f t5[ٶD6=55ot5@5Qt%6ܶag)}A \Khg٭ zcĂP7 t^*%o ɝ\U7%]h39k8tȶ5l~Ѐ&I 4Sgk8ɱa_fɊ;;K>ǹ_G bǷQL'$cE5*{}f}k+k ሷ.t;&OĪu|⩷7.V*.&0|ݠoNG(SҨZZ>OZ ڀȁ$PE,zo{Ľ{E76,8ɶhԶ (#CI 0\n\K̶ [@CQvLŚt(zde]V <4 1f%:>5@ ׼,^w}ѿ~7ʔ2/vA~%={J}0p׶AAsƸ__v,glDְD\aض1/>U6?w j)әm]mcV$"h5ö:667\66g6ec1ВZdV6]pӿ6 6JU 665KDص7 7bϨM6k6&6:΂6[At 6ҝĵk6Z:6o66.Z~:u6Y?3+`J677uKܶ`7|6N6Z5sG%v66{D526[2Q55]<4&7sċ5:6e%س s)C:56M"Y6 |6ݔK6O6]D:}86:A6~)46H5b661˶ 5D?B6g4.6^ZSy 55!C5)a 6Pɸh"~5X8 Q6[6s5zg|ܶ7ܵ,oʵP xJ6>S൛xs=磶>9l%r6<=ӶdSwdC#E \܄o6Lpʶ@v@636rJk5"{5l66tG(6a,"6!|Ҷi#|5Ѷ獩3ᶅ*7j")>d(劶7(@6#6RC6괣6F7QY5 U6MYK67^ںG6=E5P!dR7!x5mEUhC 7V5 W7GF717Bj764 760H76:73=666t6C666}76}u76&76%/cw66Dôz{`N55r5P^7`7R7>RM7 7_7t7ϝX7Y77|E:7j77c6TJ7"6D667d&6FR696Fj5t686o7\7u7ox7 6P77VMK7Rr6~<6t+$b3h387E95~d6߄65(!7j7Z7s4;6*7}6y6G5$6)_36f65E96o7óB&7z6n6.6;676"7U6Xu_66ݶBo6/6}^D6=BE)^6)76 87r6@7!g6a6q6 n~6Z6~5Rn?8d*6f5z6:6X766ꌴkOJ6> 7.64Q6 a6jY6>V5L?-i61ʵFZ^֌F6}Z5V9716@70j6ZV76k55\r*6C>t<ό q4 7r66Cx 6y[5ME6ao>7q4H7^7$7`7Kć6J Q6΁*<<۶6/15$7}5'v.y62n64o5|Z51;#69;5cn*C6Q5 ӵMP?6P*Q-(4qK~96}е*/_dõOG:&QL6 U0i:}M6O0S62F/53fQ4Nee澶6%㼶IV˶`Jkzc8)ɛM,3r1Z.>鲶Vs%Jb ;NUl5{5N55Ķ R6/kQJ /̶j$>e϶ѩ[C 뜶|$Qܶbֶ= Qܶh󘶭tPylr 3#uGT(pNwXp $X8듷UE!wo+.n8N[@T<VLE$aRj虇t s%糶S]}l{,,vW[KoGjvi2"lҷ]·SFL86‹=d?׷@)̆ɟbz˷$3X ^)45Wp,9÷IO1幷AɹGʷIeշ <ճYY ѷ#s{`L=ɷ&TJd̷P??)lo1{D qɷG6s69ط2u`h~oQKzD%۷ܓha>Nзph?녷 70%Sٷ~G~4D%ɛk8lBjv~!gy=,pek`5GwSd!>C3ƷGꫲίTU66nr 4&f6z gm)t?ԗ|@,)z춹+z} pCh򫴼۶/t5'Z56 "x5qI,6AﶨsxH`,<nuYr+϶ ,NT|6>6K&"=RC'dۍ4->\߶x͵r ! R .|36w$2cW5*e"u ԋ,6!]¶<'Gd#&"Y16 3۶ ҃rQ=9M$̐?Z@ĩ| !_>1K7 ﴎ~UR]씶-sl&p>$pS(&jݵ֧M2Wbi~$P7i^L6a6(76!(7D767bV7D`7~6z6ى:7;5s67$ᵬ6#7R770 7+7 *7 76h7v6("7)779(6G6]6B<6I=O:7s$6 J7UQ7)66 76-6r]7x)7l.67Ut7l)7.\7x63H7'B7u6|t7OC7ȇ776w77\77WH77hQ72[7H7t7垇7`7}6s7`Q772G7Q\7`776p7c `7*Q7e77h77ͅ7t?7z7H"7ja77 vU7SM7|=6Ź6`67677S7I72o7wh>7B4͌77ȏ5đ7E97=7P7Iw76 7{;7׿87ѵY6y7P6Jvf70Q577֔776H7Hz 7A6Ɓy7Q66Op 6N727=w 7os6̮6NZ79{6Sf6'6C]g636d6\,7I60R7MT=7j6R.6i&7Or6TY˗y6F6DAD5 );մ6 7)>7'7"6[6]f7Tb6mPS59׵"6U%776t7x6%p5m"6V*6 3[C5! m}/5R.Ҷ_gm5e ^Nh N&+6J6B?8wH% id679ܵ*ڵǚ`i ѶODxp)6`,J66856rg6; p/5H쭐5>`Oz>ks5uG𖶂Uo=϶@Z.y6)̶8|p]yzI9Df>6 6@-B9ŵ\ ~hӵ"۶A J56<.5 5Fd0 ̶AѶ~lIl-B ަ.K$u69Y5[a6 5chFQ6}6P7^)5ق4zj&2g̟5{X􂶶y߶6} 66Vv6SH6fa(3ڴu O5*qb"6V7$+6P 2Tu2@ 6V %6&6c6h6i^7joyr6061H6[ k7ޚ'7/*7@7I^7X6f6YL6h\05$$5#9677?6ͨ6/6n6m7F7nR7Ke7f7{6rp,7 t5hL6}6x7657W7X607X1>]H7U7­$7^_76Ѻ6J6#6Tw)7i616}KC77 7s 7/7Ed7:76+757g7H7f7687*T'7ϊ7K_7]6OY 7&q7O!6-[77>7}6MF7˕q76j7R75E# 7 R6|W7D77{W5H7~07=27} 7j+7F7`7>7%7m6O7z.x7||6/:j74_7K6I717d6,776+v7 |7ZE;76M7%7ws7H5H76i61[?77X7+-6`7O7J7?6)֦6w=77a6:60)7.c67t967V777j.7.7F7@A7Yyk7[H7nA~727"277SG77*S7^27!7 66!7m6 7|+7a~64AV7ǰ6~6'iF7 6G<%7l67B6ݹ7( 7<;L7_<07376/6W`R66aM6Fz6N-6M+656,{6*õ@6r$^65 5} 8617`]6 5 u6 "766K> 34? +\}h!XNε66FX6x96GlX66H6঺6po6C&w5> 9}G,GǶj}߶ItGܚ: 5@TfC:84Mc{ r*6z+}F}4?5HHF6K5A趲4V6{l2Fd36b\#p7`6=7+J7s576\7y66D6:7/666-76S7Ґ737+7ն66O6P5.7cde2_6E627b5q6<4x`q63)6Z4PT6616*ҲQb6pE5v6AEiZo6+46ͥQ6a6ԇc066)5NF55g(i%rd6.&6 6SĿb6pgd=6C1K56 gʏ6O36o#еNԳ~6d*66s6?#kܹ68>5،5ZWOcζa6w`]@4K64E%77-6d6H'7١6!ȶu6VuI6O4y6 ;4K6'G,W7̤d4;6ugE6zZaT8 ά9 LG5ή6z6xN6 `:66w`6n&6D϶Cx5246r66v67!!4е9 3˃505$!Bu3TcCu#U5q667dž綑5ظ5R[5\;۵,rz4Tp`&q#+.+ 3b 6g|ڀٵS6B6^ʶ6s)7l5e<6Ĝ~6)"2?5 w-"&f붽n[5Mp6Ӧ6j'SK (2#Ld%Nm϶ƃZh-w8N!V5.]wgф`- bsE3^EII @b0 I E:[<$"4:嶨42: 趝$W 6C< [W)0L&`OAܶ)ƶdl0Cy}g_`#[s`QUG$"<[w,陛a`c3gջ~C}<3QT\u2v`'CݻPhJMFLⶖ O8z%'!J (7Y-]N9P $r˦zdH!r Al߇K33at?ݭhjӷ" <^v3k-btD8_OWAh Q&cWq$6P'0k5B!>Giꥶ}R,?p~$-G;F7$ ĜNB:FP P(bζ6㶲?Zg@5̶T Ul׍8I 3ܶ5V2дujq,`UB4A. q,ٶGcA{6(tUyy!E^SuҗxS6r6RzRt6n%5yh&' " J"g FN\R]> 6fR6h5lb3 0+/rxf6q/6C 6ö"k557B9p7V6] 7w~6O6Űl6 5I#6O1ڶ^5Fc&?*P&$ƶ5557X66e`7 5#J^7ON6@h6>l666b5R6"G6YM˶v7ҶjY6b96 k6T6BMH7X,6{#7@i&6I:WR6ƭ5qKhWz6}67:)g666)776Qc4767, 7z6Lu6Ns6zdx{/ޟ|6;V66_ 7i፴5 ׶-54A 7wu56&.86GY6ٶhIյE4|ca66(7G5"d6 6bvm6V6 6Jx#Bײ6U467"7Fl7c:7A`7DK7J7ki7\7TD7!7B97~j716Gwk7,Z7T$,7Q@7S6SKO6K-5;)7E.,6/"7"%6]66َ]7"6y?178{57H7Br7Uo[736oA7S\76'72De7K7$7UJ7[7.7,6T6T6*6Ĉ5-7d7$W7RL7Z7%j7j77]7;7M6u6b% 77f=7PT6{6 ? 7x55e676L+>7‚5 6?7S6776`J7~6pr6R66R66s6_5{^7MpIQɳڶͪ KE*H6d5U86a6Bv6+(7"7e66+6=Y5>d 赨|Ŷ߇񶏮OI{6lNi 5 VwYQ(xpԺ6̇~+x6vĶ 2ԧ,]Ыrm@'>ö 2E3'UYǶL>5K[u䶞g6 pq6Q{T.;4jҶH6 Pu 6?鄵(>x6mH +Iݵ}صJlal-.66V7㫵t6M57 |6b6yͶP6,6CZH57LB5)5SE7rK6Lsxs7Doѵ,̶+"FI^K:αkѶ ϶僷ӅmI'7ry5Òӥ{}6WE7-!6j5 TT5rѶ!'p涻\S4sU޶5lkdۦ6F6K !59H65,E6?1_C45tI$ǁ_#H6ߧckD$6J>3(6в =@wV66K"/. ¦ضZS Hvʁ7}áPO-㶱JC6ؓ><N6)6Ҷ;5/0 .z1z5`q-|}h'3f8ͪT9Jtj5^YB̵]6z6ka6~߬6^  XIeqLĶ)6c5|@5v|y5U  CN@6Už W$ݶ kǶDlG§"5άb=5[@M UɵsB5Z?b8"׶jIh!p84T=id+%5&6"6 5w }@5ʵanj68۶=>u6YY5YɵHU&4jeEu)o׈6Ydp3l06F-6 (5*5H73 6gMs66okZ6 6z6K~5"璶W5H`656馶z4 46qγ6\c6IcG  7m-6/6O7^NgT6l.Iħ5`57 ȋ6Fj63v6|E6#xw6566-g6oW7v06 ݴ)n pȶF>䶕S6+6^J 6ߡ6fW5=.9c<5'Ŷg5.:36gOY6K 6R"Vܵl+r 3658,5ya%!0uHIm6Ejg 9c˵;js۫K7ضf+ƆĶuǓ6Ƥ6oVS6Q5v56wZw!2'Y[5l605oFǵGuM6C|;5(O%6ƈ9[&N0# 6HvٚԶCm6F5|-fP4}6,5^EQ6΋ص;*P1ն2sI%3vdYD4޶28_qJR5beX5t/4P 6b ܁OEX뺶#4׶L$nN2?6}6Q5AZa3o, Ey[Db=3rf2`k6_ͶǩڵR6e6l566v77i3W6 4:6;6_6l6~liڶx`)|\ D5) C)%XNAh4c#G5׳,|=7k5w7 _7pL-6b57vV6~5.3,2Z6\lx D6ڷ646Ӈ5y66mhV6'696|"67,6D5D6&76PE6IJ66dN6 6~N5}4J6zh%f6/G6#)3767֯6j747MOO7 @J7h7ŨD77L6(7Hy7+w6RE767$I7w166q 79 7e=7HJR7 G7 707GԘ6 D7E7Yz7T?7B7/7c6t㴆Ƕ6AK 767{B6D;7X7e)V7C7HQ7sb7C77R7߼76+77k6e 6¬76i 6H77#7\7_uH7b6|6ɚM7H7ee4-6'=66e7<5(5"5ն⪶6I}5\55~6B 66Y66]&)7 5D66M✶q6,67~my6}?7/6a6y66]7A6?07 _7g627I5D7<6\{.z6u7u7 7c764\7t6Y6b6 *6W]6[6u=7`P7ů67M67 ST7b7yA76*6#ς6u6Yd6r6t6x6'7B6V# 765>:756]67o6Y79l-77c7-7fQ7|7*756P668ʳm7!7K976^C7n67H6$7=4X+7f6,667.7@e477LXv7{9637 '76\_66N 76 Y6!7+7X6Td7m 66@X7;x6ȶz7]7&77 z57Ѵ>7a7W2_7a7E 7|I5ov 7 K 7 66z7(ٝ7777T7u76O77=<7P@17p7/#766626e6Z"7cҲ6>6F7AD7 k7Ε7I7ş67KBy76f70r654u7eh5d^6M616r6w66nT6Y*77ٝ?77`6[7 6M-6-[6 j64.+6#GO86厅6H.#A5M6)_6qZ6u4qJ6q6Vy|5&7K,6.̴7Q7J:7o654I6VN5 ROͶʅ-PsN6^ma5a ٴ6'784l]7T+656-R7]5X6x65h#064c6IW7ѯ<777Te76176\7t6G˵Ņ6AgӶz3 7#]!6ɺ6 ^7ܙ6I56r_6Tm65캩6&%4 o6賰*56m07Gk 7 v7H56TDy?O5ڋ[EQ6yES7X6[׶/"A ^5=V 7AdG766ܣm6A7O6 3 7k6\ 6W܆ 7eضƯ䞶U6aw+60t];6㮵c5 67`>7V[7tl6*7{b 7͙66?"6H6K6t6?67-{Զ㔌۶ 6K 7[3 7cQ7R6#`787!`62N6ީ67Q#~6b;5a6D6?KvE7.68 7Jt6o#6p766^]I7U6(x7&27ODT6 70\b666n6k6Lgb6=65 ;6776_7$7(7Ș17055L67T66|66 p6=3Ƶ17U96g6ε5]6C+766p}6[z766a7v6zY7K7',F7V7R 7/67R5 6`A65?6iE>547t6X77k}P66C6 7%͵z7>6766I7@OD67NJ6>4а78h6ݯ,76uŅ6\768#76ݫ76c&7%77x65p6P*дFN.U}ᒶ%6MLJ6Ӏ56߈7S7]7_}5?7@ 7-66:636T6F6^6}˶wA2F5\#67x6a$$7S 6ŷ7cR%48DMX56&B6㴁;595f* T5^5rN4TS6bЄT@26&]/vop @0h5yYov 62B _5ﶶK.u<ضQ64P6Ak66Ɉ5\y6в4A66hF].UDˢ\mZq)۴*+zX4U #˴45wl !6Ӷ<6t-66[^n񏘵oAh5 ɶ52o6z3W1ֶ 6.5^X6*6353w5ĵV]u5- {ʂ5Ȏ5vKu6+쬶lk Cb?JUZ N eqbBMh4ŶF߃5JŒ6IA07m+#6)%R;6;)6oܶqʕp}†4&Zsc6 96!6򂆴s 5<6K[aADvh}\tkyϧ%&&@ S6"bWi67a6_L6i4TͶʏJV}3a阵b̶'ʶiQ6xzi`<a6 ?5 (96F#7@`x  FSr%{f`ppNIwٶR6:8P(4>F_Tt 7W62` Զ%aC41RgE|R=ĄZ{m ~N/6_Nrys: ƶ/%@nl=Q랶Թb <')RY.L=@ L?n>/>3C66cPŇp+4c!4s5 fnI);6"4=S6(}6RGr6\684Pq6Z' "<e4k]*F6D+h^6pӦ06# 75N6/Cbe6M66X5P53A6`6Aq58#:6:S6-36)m6]65"(7!6I76ғ6-746K6"1C6my)5䂭zƏg5e6676w\7&0#6#7Z-76C6<7Dl?7Mr76A6pP7.76m66b69E7$l6u7HqE7u77{6v7-6<76ckINCN GD4;3092Ʋk5 =5ٶ.:6qֶwThp i6Ze3Fr+G536#\wb:ji$ (:̶<\4o0bC9 . 0*m66j5KQS7ë5ʶ~5JZ Wٺ,E6嶲J?fB̈5+'<ɶV3Ft1CN'6;/2!fP܋t׶|Ѷ5|2 `^϶hh%J ]85@y1r|}[#: ԯqw: Ѷ[ض BhIKy 8k0 TӶww<5 P2'̶,}6tYφC=;%XQ74ضj5F4 K_VN6]=4&heˀ׶=*5;}6FAa۶sĵxieq5 6&=Ro4^WȾ 'o5 7pK+JͶJ 7T@6BjlccZ_6M6x-6)kjT/灶붂ț?>X^6c6 2R6G+>꼴1aѶ( ͌8ö!dd5Z'Aid'߶8϶ŢI">#LM0c? ~ ɟJKzspؘ@COeHF4T:89H|jJ=(]UCn!BQCi0EH hv:+m+C5LkͱɄy6Q]%Xfb&u]5_Y+\<8L6vD6ꙶY{eöi2{+ܶf"6=d5:Z 7lеԵ56[I_6o )I3Zx56)NU546> 5QER5Wސ4؍6*t7L X= 6{A.h}C<ȶA#7"նYx8Lz$6C27Z7f5# 7~M5DD 6xF5R6,/:bv 6%95(dZlMʵ= ^kq5n5N;ɶ66I{56a6G6n4%6Q6#5taja"}!3&ae#W*u5IN̳1J^Ѷ-{D>5?$E6öy -+M< *IJd (f5ٜg6F7 6GAA )\KnA(W/lUGs1@ڶ㵵qM5^s6I4Rλ5g6༵檶l9d5\O6ѡQ6T7R.768Omi5PCݴ 6sK;BmvԵ4!L5e6mhٴ 66)Q6nt~Sڡ6BmH%9Uny4(M 6?h>7k37w55?6p /05Ni8 ]6 43cصc Ӣ]LJɶ /mH0 Ѷ޶WܶjlxC򲶑D8h}ԟT6wZ\%٥m&ent5FAW(Z6 65ڰ>P"!5' 6D:ִb߶va.!T5)'涀8mD%Rg.bP ByŶYUhր?GN8RB|B6ݶ[Ĕ zk43|˫Yi4~a!5A5yضry౵3-/PE='c=W5X6:5flkֶ$ 6n#E 5l}x2>54006Y%6Å5׫=W6P4.5 6o|(7~6LD6B5{CK5DHIW6S}ݶsx5Cõ`* mq6 4~\6646G6L26)6,з666$v6Kb61a 6y䚶FA"6^BI|O52֌a$U-Yɶ{5{J.6 m51x 7Wء*lv۶D\jU>ҹ(0aJmn;ŗG*51`Uͥ3u "YQ`1߶|PDŴ;H>*K&-ZXa.'kD54OltVPLGx5u5-fj~1 ض(KER~fRgx1O6O]:3#ߍm"-LCWX?EysF#FNМ6,' q ~ u8y/*ǝNɒ %z/(+g.iܶG8Q"vivɧr,N.8ٔ6 'gc $sYT!ﶯqn.*W|k_%OI:{1|g~6w;6 ܶn55 J6M 巶Cx5lNdǵ]롵WrC5Y";)F6aEA46L΃5Եⵇv|AYȵo-髥 YW˴5ֶiH64+5]3ڶ9@Ӵ-|}k˶ֵگ655; 7"6J6y6L[6N6@Q1$asC6JNe@Si/ZͶwnZs \{Srb4;58Y6?ﶂ4'嚶K-4Be5G- Fx 6xD%eMU6ijײ 7ć5,[65`Ƕa`6PSpŶGڈ5]elF65 66OYʢ;5Y=S-6@440w4-54]5\PFX)5P$6B$5v 7U6+27, 6dk65 B6(] ӵSն=4~6j 7m5%6i6K6Okr6Tt95LUصtLX4 ݑzDNCr#5nRK4!6$YU4N''5K0)5Â6O$5Z4 㵿ͶQqeȶԶ׵H7жж5T.)#Đ6(5״tSl7kP{Q`(趗75춲:R#A5|+勶t6k!⫇6Ef FB%(6Rmiӡ I hY>Zе g6ѶU\6m){B!tձKp5#y FіD0n5, 4@bض+5dܶ.Vڶh4{ӶyGƹRМ0~*oLKnW'O~;cKFXV96QM4t xy3 0D" "~ Lɑ, ,#< c`-<ʶ15'35ۓC`oҶ=i?$8$`5466OŶߙ¶tx eٶ5^X5m4,55_q6C6*6|M6`_`y5dQ1P %2^G6 6䶀6"'5u5=3%q϶ł\6V)5n46l6X6U6m7V6۶366ǵʹWxc̘[5c5_ݵ5E4d6)6c5ճ\6=U6wK66Ij5>$P46l|wyIWѶ(|`صdC5ƶ]+84įXᵛY5.45p86~5K5n58r45v/' 0b5b=!'bdQJc5)'7b[o;^ETC5"H2@%敶i06g77ر$Qvc PT%&x:'*5N춫j5ʊ6V6|^[6a?7 7B66 H6ٵi4 3e6<66$ꈴTM6L 6@MFG6q76m737wJ7Yj7cU+7Q5| G%qW(z6!26I&77@{7m75v6e<)7i7Y 76h7靿6T,65h6<`"776/+77@6 7l7S 7O2)7L76w7z7!? 7J6 e7J7p6 67I?b7966"L7:D72 7,6=4526[66,147JJ65.07 ջ6.1646ɸ265L6}7(H7?7QX7·6R%7'vf6Z6k#5$ 6xb6jWm67=6)W6= 6OWi6 v6$a6 W6%.5<>|ѵIi616mG\6T7*4Vj6qt6_76?QC66is6555!56Z"! 6 O756ܒ665*ټ4Y6Y춁57#64:6[6(M7 _6L7&7b676765R66ww6d7򡻵@76046YZ6 6rg6EF76|756b`6p6766T_76F6$B4[S7)S7E5697U7O 6y#7,76 f7|7^f7&$27zx7eK7c77\77g66C 7H6&7J6m7m6_~6Kf7ƀ7&@e7?7T776ӆ777O7Q7"Z7Y\7&!7w7@ 7^h7)]!66Ǚ6N6mR6ܖ6^7{6gy6ɧ6DJ7^6b3h?hӗん/4̱6 7`k^7L7#"7?O,7G~6Y6R$7z6`4jѵ ܹ5WE6%ı67L6NI4m<56?AyѵM69y65|656, 6b4m 5u6]6 t6$T,7t0<`6#6N6C{1|g45@6v8# E76ȵ w9(6 쑟6G"6⡵IV7ְ6:!%6QŒ6G6^=񇵂MI6 嶞4M6)L7V6&f86qP6e66\6se66AA6G56,~77Ә6yel6K 6o26dN6ɵ586%6.1Uf6V\M7k56`w 75{6D|7򃂵SL5ۄL6[>i6v S6f37Gm6Q4 7W95K*7BG/6c6VR7S 7$076.' 7ؚ%ف5H V4N(6+HM4;f5h4+66ӵiq,7"7x 7㭳\6P|dܶ2/;=wGնR"0YS! gUն엳ضv]Y-65HBd6(>X L2ϦIyj #'6{Q&L* @ٶ\F0eGᮋ4f0!/x42 "¶1H!v1zk栃nV>[㶎8LʶJJV.-8(M)˿;)?@߶V=1_-9r%e_(P"{%hM:ӶgN6ʶ:+ (,SJW:jKib*:bd{džF%LW9֋7#j>(l:q¶, qW0M̝OIaDDT9|$6嶻}E"ݵ |C6*5b66 I󵑉y167`J,X1x!Gn6Xw$¸4ɍ6~/a6\6]w6 h665xߵ* &6L\6w6-a 73%6#6zs67 7_6_'7#6>7h7la76 6l鐵^65u66e35_&}`6lQ76!7r6*:7y66޵*,635Ӷz2ܶJUt䦶'.5Ar6$;a7ga)6b6+74p5}Y"E7$?T}\75h.'j&s/d5=6 6t*6 6!*6Xw̿6Hpk8 sd$y G$Sوy\5/75͝4:7`ѵ% 7X=I7Q6P5y5؊;7>y36t+ݶ D6J3 'N&a3} 7G`w\6$60r6755הn6mеVVֶ c6t665p276/j6a$4fU645춪^(4})3|#9[l6+5h5ӽϵߥ6@66l 7ƈ6X6k6S6)j 7c7 7h 7D7u621@66/7:5_6e276T17c5 6IX6ⴶ$7/PȻԵ"65!,6A'6˵5^87c6ޜ6M7+G7@6t6?7{O6)%7U7n7.^6 ͵94O6Y5tf7 7o6f736D 676WO66Jۓ6n3j6r+Iq630G/o66ή~37 :6 '6j6sX6ڃ6e55Vq^~_h]W'NwgͶm&X6J41&U6G+6./'㈶NnnGI 궶 Oxr@%$5}h586 (i:]0>(4gt }KqQ 6SozP5Gt$67-6(V7"I%7ۊ6Hֻ3V6V]5%e͵xI5s58 6m鵄q-_5E4*6:4\6Ź5 \7c#79W7w 7fR6Yhn7M|6k[6.k6M6SD#6v/6 X6õ6d7=@7@7cK7_7; 7@7~A7pwY67,7k7*7o76/[667L7o7LL07A7 *t7q;7D7`7A7/R7`$7SZ7/77+7èF77>oW7+7 E7?G7`M7H77Ao7Id7ǂ}7{7]{727e|7~p77vB7+7~7-7a7eF7X7376a 87f276s17qp77Zm7j7Γ7778`7K7K7wE67t777'666 y65y6%>7,76=b7o6Jo7=7:/7 6gh7ہ6 EN7x776җ+77 <6~Rl7"Qߵ T5|2%7A&'7s75b;7t5Ä.6@7Nw7=6`666XÕ6Q6B楴F;66{ 9B<6ݍ6DŠ5 VI16,t5I 7Z!7E4c6b?57_Bf6fU66Z7!F>7D/7%6g6 s6}6c5@P97a0V7 65646$6 6U6^5n:7!6촀7Y>7^7<7Tz7V73/7w7)7TG76&r6 +7'5Kw765u)ه66q;563_Z6 'N75H7[#6 7n7U6:7R"7MY6 =79x67P609766U776746Ic&706$ 7O;7687X5Nΐ6 5g6-5o66)7ՃL6786;6 G6P6z6p626>6z 7D65w6̛67*=7W=%6\6/ӭ6?66x(7| 6S6 ק6V56}6/ 7$7d7}6% 7\=ٶ0z97Z=F NG6=ї676166f"716=G6n56ia6 Hk6\5K58̏¶`(O?H4s6p6VC5|96O6P }62 7*6Q 6mC07w6068 F7 n6-6MQC5q6UߵP&07-&"36q;6^P䶦566Wqg ն΋--5)45c666F7S6J5/  n<%6ٮqĵzV`56`聃bxv&)YqD쎳NQ7=5 Ǹ5q6YҴ#6Hl3lt"6? H 56uv6k.;L4.j/ʶXVN.ol쵋F53vʶH4|t)93Yn4Ѕ6h664Gt6V$sa"@a|R6t7hJHj6u۶tpsG]DM5lz'/>4h5-"6/ b59_?5TpĶڦ&C(͓I5MAB,@󼶚S.? -LΧ3hչY 곶rK7B^66 7b7wVN7˵†6665AD4$)6 P63%66iJ7O5 6ws6-07ƃMb'7&6,4+6^5k6b6oo7YY675Gy!>N77y%ȯжTXk86je#(&ŶQ6 65 K%6V76%UgY6.+6zf6F773cp66Ixz5ڴ[r5s66'7n66Cb:ᵡCn506;5@H6 Ģ<{6hH`h6~;"6oH 6g#6UJ7CS݋6on5{T;66!陶Yd϶׮.E{6Kf56U5j7 L˴t16HZ4!6kz6965 \;663L6+7ѰE 6/6!66 65dn.6%56<7=NM35'j735N566g6"ْ6"Z6gE6w$T7Y6v5R4H@206[087F6.V4%6a5Yȹ{o6V7V@6A>6.6,6*(7=6Ć:VYJg ޅ2<5 KI6@:HM7=6ڶ6G5#7Z6Kekx_ю϶H1$ lN.o٭=}5>6h6ĸb̾-'ϩ3 I$g4%T*V4D&eɶw.I)&͵?&V趁+R϶0>{i%oqJ%_R8dS-;Ķ(GFq 㲳[.Ң4@6WEA`6ŶNuE=9={5Go'^9^ea޹l'66^6U6/_I6o ;5L3/hu#I66'05Y.5 5@}K9uѵ7): 6 ﶘ5u'} 55FK 05Z#W554.)F?}6J6 6X5y66 vc5x6Ѝ6GD޴9<=5' 6Zʘ5꫶Eʼn+^e65+u GD>1R6r6o E 5ʶ VOW,v#: U?׉0`}ζt:Ҷm Sj6¶}۴K6TV^5H-Tƶ*D"w5׵~E+t16AqU54!vJ7`dG,`#c5c6РḟD&Ҵy䰶Fئ58&7[+ǶMO"QI1A5%'ն_}6!Waߒ6ƀ;5t-8E5:y6у5/س@ڏk6$e"w@g6[`U0Mִ6H5w5N*7lX&6^5d`d#%77V6n4+5p۶=Y6;'(=25i7__7 6纶3h#V6?I vT85ޖ5CA65S#45E6yռ5n)i2Fֶ̈́.㶏3h6ȧ93G׶H ƶK5|霶(|{;;dfL/4DS ԕ 4gZ5A6Ŷ54VH2}`5B6ϵD66R5NuFTٵTFN2N6?g.ls6PɶVHI+5H6˩1;<6 -O6⣂ mr@Y-̶+$b`@Ǵ~޶:xӶ4# 578j{6{)J:6ѶŻEN6osMI*E6S 4mG5?R5(4Iش6,x6lY73"5iN6<N˵bõT 60_R5>:2Ԡ6"476]6HǶul5,C3-cV2T>6g7ڽ6ۨ6G4666jѶ?â6l9/{C|@053C 4866{k76a`M7F6x5@666ÈʵgG6E"67 7fߐ6G5%i0}4pB5w4sd'5%6ddc T6Yx#6V_'}6+w686V066{{64'6!-6آM"6n'O54?͑6$< d5sRLs164"75.5ʣ6cõ66若G a66o6:@7"7϶_59z57JIͶͶ'c50̵q* 6@O61Q5a7967J7ʹ6yS7>E7=66S6;7K'6YE7 5/R6f66$6265 L7g6FY676]*77t7f6j0qQ7'F6U6Y7>Ϊ66b4$7ާ 7d3m16L}5~7F6P9677PF6)Y7;Z7H D7(~G7]727(7A7{6>tJ6 7ш636P |7`6ʵ}6616}:7UXm7٭6gu7F7:([7 7J70786}7dq6ݐ7 D7b7 Ճ7]77|77S7f?77(72n7<7N7!7oa7X7kw7u7/77ĉ7/7@7q^667 7j7X{97+7ϡ7~57s7?7V7xG7ׇc77Ddk77*27b7 T77 7n),7 77x77F77h7/777(7E7*27Bn7ӏ476f77%66h7m6'6Mbz6ږ7>767''7r<7am7T7Օ7*76387<4<6x56еu6H96!6ϳY7N6$f7j6CJ6`K6k67i5N6FO7W 7Hj6C7/7R7i6 76t6O67,97:$r7Z6m6G 5 6s!!57)46n7-ٌ6{76w.7۴6Rp6^P6 (7=Z61415E/4e6jA6nk66_6ݜ737oFcc7e7 66El74L7=#7)7KG66ߏ7۷6Ëe76"7ă6m;6 7U6_ 76R7Ɂ6Q7Ŀ6SU756\4o6$7S6O6767'?K7ah+7iQ6'?377e7"7U 77,7ޔ6Y7672D7b.6#t7"M6Q64 6 5.96r>ۉ6!5Q36c276]U7;"6X76[6腒&14365+93W!6ygL?}9광.!e 6]Gr5I56r!6;6K6E 5I`ﶴKPKg#>Ӱ_s^ 5lx6u]5`596z%*6²6qš66ɮ5+5-1>]v@D˶.jv@V&b?X6e5{ 6Pװw; Ѷ ȵUI_gnݶ^ X\(ζ{^ JRㇶ%aX 49W6>6}65֛Ҷ[e6򈽶 6 4ƶG,S|!KGG|m8K)#5Y8S 6N(J36M{45|S66C5Hzk6Y56O7cjc7ny6 7X 7(4\Q$ҏ5z7^:6}6d6b6J6O5:6}`6Π+ZUO UT6@{*\a6X6:D/7wlRC6.?64]ܨcQ̆>* 4JCȍZxp63Ů8(fL.q!.:fܵ?XǶݣ6Ic6W蚵FO66+6#7Qc]66&+7_5U8"6Y?uu_صU"ǐ6!%Y6166=6ÝǶb6-6勶k7]\6rqĵ61B p9}ն5;lصw׺ m66e?6,6+5~)66:a7^6*G5d?*6`6ح6&57}5{7DK% IP5eGU+/OIiRhZ5 7#v6_K66 7<766,7Fa968@6`0Q6_U7Fu6; 6\r6z$)66pYk5666*96N-76>3s7]^b7r7s̵Y7QK6\72.7,N7дaH0q6;6m6ˊ66KF6+6z6u$r?8AL3'62% 6T5ﶀM6x*76QW 7624(p76}Eo6X6 7A`6@ 5*5G ?J>2T\Js6Pյ .65%z6.5㒭64O6EsD5aK6+5ic6%ʶXH6V5Uw6Vݵ87'Z?7FKN76Zڍ }4jֵ6PR6^~5󈶒56Ȉ5K6 =7c696)˗64m51 5(2@5(6Djc6ϻ/6Z7h6K7nٶd77#67CCj767e6e6U<66uJ6Pv6,6 'ζcg?n26O46y6fĵi6ɒJ6 :6Ӈ&K4:-`n6g=g3ʒ4Ә?5@[5ꙵF6J4d6|Z(6`F7CL6ҙ6D6~6i&x .L5M6"Α 65G6D67[7 47P6C 7`65Iޑ6KG?4WK8Ŵw6K6>66-6O>O[7i96T'77 '7aM4p07 sK61K6Dz6׶84Q6a75iiS7LJ5E7aa276T4=7=66R6B6x[6ӽ'&5њ44iǵ,c#65h7|-g/5)G6߈6686=ĵo^56ߵS8346>~ʶ5Ү{2C,.$Ƌ6]%G?686ی6Gb6kKж&7l$)`5ζ7@F@F8( Vw>#ڼ6 ͳ}6ɵ5}Dvr. 6ե 5-f6W7;̴6/eEcCهA #ԨF =WF$sm b{5x^M1Ҷx1L^65=~RJ)Z޳X 6yۧ˂QSεKbϴ܈5n5z6667 ˣ61^7Rc6:ڵ{65'R_ötIL'5R>:i{6.Kd5;)صܹ( 67Ķڅ59R\6P5I05{16`{5WϚ66}ԵUt;/-N_6{6{i46ʾ=61q6ɕ6)4d^>7o#U56AsC]l6515oM&11vuCO#%5Yq|4ƴG 56Ȍ6e7ן6vI5KRasR@ٶdŲBDY5#,{/w,B~#6GΨi6tF{\@4tFNTp{Te5}U\JJ{6 G0E30- \l@2?Vֶu|#f5>֌߶^ N˶и-VͶ}lYSRދ&u-mpPVe›@Ǹb꛶C5W[gS"ڃPzItq $k, p4dԵU6fKö?6zzô5-1Y43ɴ4uK&r#/J&S5-6EuaXR5 6 * ض5 xz{DXД):8x7&.7SkN7>6g-6/7O-6U47[$b6Դ>_qY66$66606F@5"]¶C趨"X,s6δ렶B66\(e6d[I5Cal35g򌶈a˶aeL6~!ׁz5݋5/*96w5B6>6 6g` rl G3Nv3Z?1$6|v#6 QZ$t<6:oxmv6ʶn=D (5j`&nJN6;5%@6+50X5_6746@6Tൠ5޷95_v6l655I_p}JGQHg6J`5~8X6l6ɤ6Q 6PM g8ubgԶ#5(6868]gG6Sme6<7[6b`䶇'"7[ 7nv6Qx6E5#˪6=h6E6Y&65@ɵ"75(A5F9V6of(66|6v4,6W?676~j}6#7H6 Ӳ6p76{B7='6 76 763&7@7B6 C 7A&6Q7}<7p_7H]7&7{66rc07Q7X6l7ėD77*Եa7k]77a7p#6K7N57C6!7 636+7c56d8-57^6k67g6Ъ66 ܵL7^5Q$07w62H,7R|77>7Nx7767,7`#67167H6t7p56(7i66V7%c.^ǀ6Y"tͧ6eW7G64xC787y6q7ܔ6Q7Aw7n 67)@6u1a6 6`7}6Yx697y͈6J>6`5(5p{66 7 7\7$6U49) 7C55}i;5Z86Sq6k?5q5/.74 6z6ݙX&x66v_6g>6P6Œ W5-4)ǶG*B 63? ܵ0eʶ۪H޶3@uMQ]'}O(JDL~wR8u`J7>$<ֶ M24kz+'u̦x7綊~gc i=l \zBue r;߶zo}@WOq"~ &,궧-2*ȶA5(WP1Mj,,~˶J;41\ҶmG4A~Q6˨5l5'TRXF5섵sN/6+].lTNݍ:=r8풵aÈ ߵ#`!o=Ŷ𿈵6ϓ rX< >D6QCZo8fM=Nu V^5Nþ; 喝),(E6R[,~#L񀷃m Dpe_ѷQ`jI?stSڼq޵a84fD168Figu1swb&xF&AVB Ƕ>:&fϵ"M/CUD9`Nc`j᪴5+'Хж:=uM[#!3F6;ˬEtfjKݶ9~U[T2T.[n>H#o +z`lKS"kH,KK0c>iY ̶E,@?66q2RA6\dl,p)Ӷ~t0)!Ͷ\냵ֶVIA5.:0 4Tlv5z'6>b~paTCDkC<^9 _$3#_3w=;6X5#EJ6WᆶSy1Foǵ9&Fꦶs솶ʵߐYA8KRD7}U@7:oĵ}ŷSQt 9H,dܵ;h.3QcJ6,@IE@A @d[r,g?G+D5Iݶp݀b…6#X:u,ܶTY16 M[65&Nf6l2)9K"~8?:.'rL5/5366lfZz64yE6=tVڲWKDU65#~e5N+##,3>_%(6޶ö}y9iƫUµ2?_!:oe6qT=z466dԶ0Nn62W-qWR+6oﻎ6Q[ 涉f.77oO!ζ#'6]I+6\Oor2\aWհ0`~婶4X̶MFͶB\6o`ʭٶ{ϞX -.w$E˶[raɶجPն ۂ6,2)~N|Ѷ5S6 k6v]X6dx/6p;򶡤Ǵ5Ñ4^ڶ#y63X+6#~69Q7.|6ʐ 7Pn6b6h6mS /={7G-/轶 6 5O*H4є6$7\X5W6N6 7B6-7 #7Ӻ+66q{6/52給G6*B6۠6킶Vq h4u 6-~7Z^c7j'76%`6z%7"ؼ396œ6_6+/}c|7I o6o%7Z 7W7ޱ7bZl7e5=597606Q"7ҡ2ͅ15j:3wt6ŗ_ X6Ƒ646[ț6XE7.7DO`L7Y96KO6%6r~Z4슭6u6%5:kX7ut67i6D766;6 =7YL6Ĝ9$4bF6Ƕy7+=6{ԁ626Ri5p758=7y̶7V6L5B۵b7&6ms)6z2O7`߶y7$4b)㵅!8y̶+6jP66/'e6;#67صPk6%a5 | 64&6DjR60,62${E7m6H#?7hԊ6iQ7[M754ʨ6YF6m56-6F7"64n5%7gi4I2/4<5 ]6g 7e7ݐ7G667 O7( 6D*66 @666k76M7g6_S6h6R6^746J6qZ6v6I6=5-p657}5OD6G53f66;4mӴ66#uM7=6fg7ͨ6߱5<6aga7ize%&7l6^7U717[6A5PBԵE850D56~6P67 ^+7T76E6NN7h[7*46\~6<6I56}PL6R6}66EPC6goK656lq6 $4b55-4SN6r6aޏ5i?6C5pW6˲6[$76b6g6q6- u6-1UoZ6劭=6ö%=µlM 6O8֩Qg66WtL7 W5I7<|6SF6G7-%6{6vq5Px϶1!{ 7>8=46KP$7Ep6L0`6D58;𶬐öB+6h=_6A\6 5 6a6v646W{6M75RU7466`u55RF c$k6 4-6?6U6 V6p6v6j56oW5j"7Ù50@I6+0556E6 66O 6]g6z67ٶ#@76Bn:&u67.ʡ y4C306+6736X6$86H6{ˆu+66^F6D6LR K 5b6^A{޶ 9EܶYYͶVae G6S!7;`UW5T66Ztw6 _!bkwsɺ6v.iB]1lDsrkEY h3&pkxPq5 6EFSF[3f&6n4B5d' dSPA67ʵg4G)6 ˬg4Z`4}XX_aJFR/6Ty4c6v>xb͵ 06PM;6򘶳޶"õy6{5 36 7ģO>44نcoT&55򷶭7'6nה ($F{z6:E6(m˵ts16B6?6J 4E1 b<]hʃθ_@XKRL:} /1s 32?6K\6S6mlbR}5p^?ř6{۶:+Nݶ@n;a8bt5ܼ-5 66?ֵ\Tɶ*`6x&咥c4=iǶ"#555[2}6c6Vs7/[S6J6e6ԩ>6ި6Bs4hhr'5u6I_6-76(7V?6 ;+7ͳ6q6u~1UM36D7o&665&\6Z66ɵ5(6D65yF6 6=˟6N6`6)"F76)7H 7-6?<7ܕ6K67u6~M66:6‡6q6$[6G6i6"6o߂66q^6*607767 56 77oX6YsP65xya76W6%_65#w66dW_5*q6i6k5<6P6F55t(|6'6i7Z779u727{t7506X5LB#p1p677 7T7o4V76w6ED7707E7,777Xk77&'6F6Be6*6Is66So7hM655! 7h7U 787'7Ċ576oNf7l+7]76T7+7!767|r7?"7B7s: 7"E7u6R7:Z`7 7977G77R57_6S6? 7 ?6J7B<7Q7uy)7 686~Z56'6@5776H73>p7F0t6m;'7r6*75 746d6+(7Ml6:62j6J26 W6t 6zg6x (s6Mg[5,6N66X6<+876[6`\7P|6]6@X6Q6-6x657V79欶RZ664x6pb5Nw567Ԑ축62:D77+[76kh7}7ӛ4$J6M6_l6 Tk6~6566*5[66&N6(7W6T67mѓ6[L70æ6UM7GB76}E7T,4F7l66~7&67t67Jò6U76n7K7s77T\6f7_g676pT6L66k6 6666666{66a66L66 6 '6@6O߱6q§6z6466M6ۆ66ƍ66q6q'6Du6bc6f66p6|6l66Y656ٲ6ٹ6K6R 6N6)86#.6 p6^F6J6xz6 Iu6Gp6!]k6e6"a6^6o^6b6h6\ p6fJv6@z6|6x6fr6ނh6k[6M6<6NK,6v6 6h555j5q5 545vw5lӿ55֌595[H55'5QA5Sd5U52]4$ ]/\bH=qյx5;{iZT~M \,E?!%+4=EIKJvF3?%5 6)vH4鵠Ե(ĵa˸^Ypʵص:`tFx)2ܵŵd(d[a/^) h3€4l4iJ5_p5Y05=5hH5P5X5a5Rhk5Bw5e*55 `5ş5Z5~55w5M55~5!)55̾6U6` 6c`6Y6A66"6p'6 +6i/6B26#,4646Ӟ46836ҡ06 -6m(6 #6"616@666~5ׅ5A5Qo5L555$*5좚5h5$5W-5o5_58O5p@515E"555\ 444U4 4j4$#@4]E43eZ3R:03R:02?fS2#19njԳp.!HܳrCxs@ʱZ23T,3\J#4aU4 4 44~44J5"55"5 (5r35=;5@5 F5I5`M5BO5Q5ePR5QR5.R5.Q58P5(yN57L5J5qH5F5=C5D@5I*=59555X15iy-5l(5$55255] 55kw5T4>O4˸4Ş44n14֓4f4$44M4 4^4eZ4`Ҝ44ǭ4#4&N4c4n45! 5ì5(5E85$I52[5n5(5E5o05E?55*ܸ554}55545|6! 6p6*y66#6*6 0666<6BB6H6~N6/S6w6|6Ĩ6w6M 6q\ 66~66 52555 5]5Dp5] 5 5555z5(5=5v5Q5B55e55555IY5YL5F525J66 666*6A"6Q@(6w.6O56t;61XB6tHI68P6+W6*^6e6 l6hs6y6K^6E6w66 6666m66X6☟6Ħ6ߣ6I`6Q 6@6676`6$66N6C6 6>6T616ݮ66269n6n6B6B{666<{6!f67C6 6ˣ66B66!6J66~6{46kܗ6&6 Y66xؒ6ɖ6*z6V6:9676J6 d6y6[66M6ڸ6J,6Ҩ6;86څ6ˑ6N66676Eۄ6ބ6@66&6 W66ƅ6 6N6f6s6^C666#16U6 66[?6nj66#ȉ6566K66ډ6B6π6&V6O6ˆ6]66mo66Y66 6~_6g6666661N~6z`|6Zz6Rx65?v6t6q6־o6m6ek6Di6f6d6b6o`6._^6"*\6v Z6W6U6T6R6",P6cZN6EkL6FJ6"I6{G6 F6 D6/C6A6m@67r?6xo>6mf=6^r<6~;6:6j?:696$9686v86.8686u767686iD868686AI96963P:6q:6;6P<6=6Q=6H>6?6|@6dA6fNB6k:C6D6D6E6zF6zG6OH6I6%I62RJ6ZJ6<[K6K6K688L6TL6FL6;L6K6K6K6VJ6QI6UH6G6F6GE6(D6bB6A6=?6`=6_;6{19666k46 !26|/6V,63*6Sj'6{$6ˊ!6o|6ng6E6&666o 6+6%665J5@z555535 5I5z5:455+5X55I+55]ݠ5+59o5 5В5 5S55Jx5$5ۄ5^F5J5Ӏ55~5}57j}5}5)}5>~5m~5 55H55<5´5i555h5#5055X%5l>5F5{5ݜ5<5H15\J5]555^5t5 5Q5Ӟ5ö5и5{Ⱥ5l553555V55 5ˈ5<5V55J5l5>55q5555m5d#5`55|5D55R55;555*555>5C57555 5(x5*5)@5}5l554555 U5 U5{55,5A55X5I5Ϋ5Bu55C555V555jq55r557 555 55^535'5`55~5i5505x5|5525h9V4N.E(,!*d o_촓ݴʹ[`Ҝ IXx`X87OLyoexO25O3徚333a4)4j;4`M4]4sIm4z4I˂444c/444՚4!444戏4̼44r4~z4m4_4N4=4c+44x43^3\s3C 3n1?6>fԳ D'ZHJgN녴fEŴִ -+6 L5V$+3XT;RB\IPnW]^eNvkâq@w}L- [V+C*HhSՙ.Es6z! \M 3ۣ2VKPC~M$*ͣz`2#j3T3F8V\²|W[՞m8ݫǛcG aG6zgg익U!W[۴NԠ>[I~k}\ 0/?Uk:ЫU1YkدNݵMQ<'缵A侵õ'ŵxǵcɵ̵Fε;еҵqյYصڵXݵ;)0嵙2AC 5A$Q32O  a U8]~&gu5 ! #~%(J'(*a,.ݨ/@O12{4 6}79u:5;I=O>?FAhBCDEFʿG3HcI.`Jo6K׽KByLMƚM[N(yNGNi O~=[<:9mg754X2n0K.X, +)`9'E<%2#$!t(09v"2  n6 _ 뵶浤QݵnٵTԵ4еLO̵ǵõY!ݶMz-jYY{󆚵{򌒵2Xhwpib3[UD NdG@:4ʏ-!f'R!^BB" SipU۴ŞѴ ƴCw 𲴫rݔTqA_M:͵(&D)r-ȳ⨳T`Mq{A2.2(3Lg38u3EԮ3F3Z3414$ 4a,4 :4 G4aU4sc4o4'}4G84A444 4a444R4E4,44i4BE4K4404|4%L4{'4~4m455]5 5A5#5?55ى55o5 5G"5A%5!f'5H*5x,5Z.505'3555ޢ7595;5 W=5?5*A5C52E5WYG5I5J5TL5q"N5XO5P5S5>T5U5+W5=X5PY5Sf[5\5hx]58_5׼_5Y`5Ga5b5*d5d5Af5\rf5U]g5Mh5Zh5i57:j5k5 k5dl5ml55vm5n5-an5 o5\o5p5sDp5.+q5{q5q5Ar5|r5vr5$s5s5^t5t5t5u5v5i(55K5wv5K5B555S5r5E55ݛ5^ٜ5\525(5K555Ϣ55o5vG5Y5 5ۧ5<515S5555f5v5ٮ5u5K5b.5(5i555ij5|^55g5f55+>555`g55f5"ǹ55R5K5t5(5XT55t5 55 545.5s5_5.55C5惻59555R5A5)5\5a˸5{b552"5@5}5A5r5;ʳ5'5M55Ш5 5®5[5cƬ5H5^5sR5"5 55Fm52#5tΡ5s556z55{555֭550`5s5Ў55%5O5555$ǁ5XK5~z5w5s5rn5gEj5n,f5a5w]5_X5UT5O5&K5F5FB5;b=5}[85^>352.5.)5h$5I55&5h5_@ 5w55K44444({4* 4ʏ444k4 )4*o4W4hB42,44=4#3֧3Ax3"3É2QA1ӲO@H 55JZaKwTݜDQر'缴-ȴҴܴ@紋Р DC .aN#](ʏ-i27Cw<pA FMKW"P UiYM^8cvohlquwztxzm؈{ЊVj˗~曵K$Ayg髵M魵ڶ+r5 &긵DٺԘ_m#|õQŵƵxkȵ~ɵv˵rS͵εpеѵbӵԵ[wֵYص`ٵvڵ=ܵ\ݵ1 ߵz`ൿᵞ Eg䵺 JV1 H3cNm.KIX`Z$Q0'79/$.v@W_ " \M- `xC_NO$%k]u T jx `  , ? fU n  { t p @ u  {  $ | +t O 9<  {  Y x@ -2w3TV2[ z;<51-|+6 M9>9cޙG Gr&> VW;)'1(AK국-鵄7c%3Kn* 'Woߵ޵\ݵܵ۵-bڵlfٵ1ص6׵յԵ ӵҵ7ѵpеVZϵ;εT̵˵1ʵˈɵxkȵHǵ<+Ƶ ŵõµ8m$#!轵{Gg5i෵~\[^>㱵 iN ͪ/cŤ@c_ ^Q/\.FEژAah1_ 4wy̼֋ ԇ죆8wOM݁"~%|Hy@wt[wroz-mkh#f`<9+>7%4?2|/U,;2* '6%" MlorY 0 {紁] ܴabִ;д$ʴ".ĴB뷴fSxƤ<ҥ}V'} pzbb&TLFQ9%U+LR dz⨳gV8 1?!23[36333I3a4:4s )4:4SK4(]4km44R4},4iI4$[4l4js44M444H4<44<5 W5{ 5G555o5%"5]'5=,51565J;5 @5mE5J56Dw6tQ66K6Y6S<66u 6l@ 6 6{ 6^ 6Ю 6p. 6 6gR66+@66;4666lr66&6)|6L66M6K666!66Cy66ζ66Z666j6616 6 6X666ӡ6@6!66_ 6j66646X6S6W66^6+B6'66"6ܲ6,6@636 60 6í 6&( 6F 6 6-m 6 6* 6566$6څ6(6N6P6y66?&6_6h65O5!5$5d5P 5u5L~5)5Y535H5ќ5-55ʹ55`5B55r5Z5E5*55 55vv5s5Z5!5)5525&5a5 Z585Y5FѲ5:5/`575 5f55s5O555{5C5;35655d5E55͈55Q5.55m{5w5r5#n5Hi5He5a5(]5Y5?T55P5 L5G5kC5?5(I;5 75 25E.5*5"&5~"55v5͆55N5Q 555"4<4m444442R4a244V444z4̘4Sԑ4494{4o4a4JU4kG4<;4.4"4-4 433Z3Ŵ3滞33 {`353v 3h2zeP2k 1(>(.3p\AIm[QUirѳ4^5Hid ^J&E.N6V>FMSH\Sd/%kEsy|X*r b˜CGϢ7trA媴ҭR:.d뷴캴̃@Ĵ.cƴODȴb]ʴZ̴MϴͳдӴմִDٴWڴ(ݴ޴lANy紻ptJVWip90tA?c!19sl?U&W NˑDxϱH5 R O  t - _ ,q@rh"IL\fJ,eD4*;hNN'1)jX !?۴ ڃ !2"k"c.#ؿ#Fm$$%%&`9''Q( )d)*O*>*x+:+2,ë-.Z..ڶ/980911192'O343(445N%66\7<7U8Q8Ȕ9|9R:%y;r;`< =-==>q??[@@OA B]BSCC7CDDaEF#FlGzGGفH[H \II@JFJMKoK1KTLLMMN8NN N?OOeOyP{P-P.QhzQQQbRmR4RRR3SS%SSiSSSSS9SS[T>T>TSSS$TS@SطSߛSS3SRRRORk;RHQQwQBEQP_P-PO9O NAN"MM7L|LKvKsJ$JI HOHGF89FEDYDmLCBUA@?!?;1>f=l<_8;G:59}[8v7X6qW53 210v/ʏ-U,,o/*:j)((&i%E#"H1!huMIh_ 4Rq] i fU N9#O /+/A?޴;ڴYM״3Ӵlϴ̴;Ǵ Ĵoſۭ׾ij|火`9zo>(tj{jZzCqXhA_mVD NQEۭ;3*"iqFسƳٲ戏f{u>T- M˲.lNy8u122X22^3B>3:`e3ˑ3賖3W©3κ3335B3X4V 4n4 4|'4g04Q94A4sJ4jT4i]4:`e4n4Ax4<4!4 T44}4 4?4C4b4h444 44;4~$44G47r4F4o*44M4_g44f4544444j545G8555 5s 5Es5!k5ak555O}55J5R 55ӟ 5u"5 #5%5h'5+(5}*5o,5O-5p/5*15<25w4555`475S95!:5_<5=5?5ѣ@5TA5oC5D5.cF5G5H5vJ5K5/M5JN5O5WP5%R5iS5U5\V5|W5ՑX5PY5t[53\5]5M^5t_5`5 b5c5'd5H(e57f5j g5zh5oZi5#j5/%k5dl5Qm5m5o5o5+p5~q5r5ss5&t5Mu5Nu5Fv5dw53x5ACy5Gy5z52{5{51|5 J}5~5R~5/$55 >5Gl5-Հ5N5v5݁5x5<5|55k5a85u55555Q5565\5535\5j{5+5ͅ55G545`5Rs5=55죆5M5ن55 5p5855:5=51*5=5,5b555:51*5855555?5D݆5І5ن555[5bf5U5@#5{5$ą55j5xC5-555̈́5xt5X55B55N55yւ5g58B5s#5mԁ55'5f5{i5<555R~5Y|~5O}5|5L|5g{5z5>y5y5ycx5qw5Xv5u5t5dt5s5 r5"q5ٰo5rn5m5m5 l5 j5j5Ch5Eg5f5e5d5sc5a5 `5׼_5$^5x9]5\5WZ5C?Y5(X5LV5UU5CT5R5[Q5Y-5+5R)5(5k&5$5%"5& 5s5=^5L555P5 55jF5>5 < 5v 55'555c5E24d44c44 4y34R484t{484k44I444j4f4z4EԮ44d\44"4i45414R@4Z 444v4'm4e4@J]4TT4oK4B4 :414 (4 444G4333iA33H3*v3Et3q3^P3R:03e 37 2>(2*$2"1'k]ٰX#8SCqÉ̘/#BƳ*ճLKi~)y%,4:/A-H.,OSVq\scZh:o Iui{_][QC폴pꃖҥS;=-נ05IwA>ﶴ$_⽴ɿTYĴŴzǴɴ1!˴J%ʹϴдHҴ>Դմ`1״شٴ۴ ܴ޴a+ߴߴg|=$"4䴷C?\AɽL괬=|괢sf촑e#'WC ' w௳Pݽų8гTܳcV泡pyπ \|K# )/r39Gf@jD&K{PUyZ`e[jMpu{~yւj{S}ipjﴘM촴T,质{,svޠߴ޴xjܴ;ڴشg״մDӴѴ8дʹl˴ˈɴ] ȴŴ)ĴMD 4׹pALY󅮴U}=I``̠zϞ 2wERr[鐴:9#.Rډi鄴e[~:{oXuq~kGfm/b]WqRN%H>D6>:4-/j+7C&ˊ!v#z' ~}$:`峆2ܳӳȳj %U nZE87\J#6 (ݲav?:gɱ(k 11?2D2֧22*2t 3?3-3O@3S3'Gc3>s3- 3<3՚33Y33y33<+3l33w333334 4)4 4404444"4r$&4;c)4V`+4E.414m5494`<4?4A4E4PG4I4)L4#O4NR4TT4|W4/Z43[4F^4za4Jc4hf4g4j4^m4Un4p4s4t4Nu4ޜw4Dz4:{4S|4 ~44mp4C44K4464ބ4=44G44x4ȯ44u4444x4D4$4444]4 m46H4`4ʊ4Ƌ4L434ԉ44É46J44[4`4?4K'4π4Y4 4{j4 p444@#4I4454W44ʔ4|144"~40U~4S|4{48y4w4Yt48s4q4Cq4'm4m4Ej4Yh4 f4Jc4c4Sc_4qU]4/Z4PY4V4HQ4BEQ4WN4K47H4 F4B4MA4>4u;4874,4424e04,4'(4%4 "4!4Y44B4[4p4x4π 4[Q44t33333|3>V3Z33AL3B3]u3M3?3M33X3kx3!b3U3uC3 ,63"'33;3222t2r321,,1'65ł߲y^=& W=K]wn偳B?FKPaUZ}^beh5vmbqu@zG*zwᆴ:V[򌒴?䙴이GϢƤn>'N`=.'-MĴ ƴZȴGʴ̴6AδCдFҴ~TԴ"ִشmڴ%ݴ޴;7 贊ͬH2<-Z})mm='Qު2uN  y y= `2W )|YV:.r, Ibp>T40/5o & ˊ!""#k#$$$;f%&o&&O'9'|' (wu(P))**+++<++,q,,-7-h--.s.>.D.f/r//)/)0%!0F90F0o00˽0!0/01R 1e1/11(1ǚ1q1-11J1/1~1D1112!1P1ɓ1[1~1;110600`0u}0OH0)0Q/7//s/7 /r..*u.C.-+-h--,x,%$,+6+|++*Q*t*)3)(~Y('k'G7'?&K&%p%H$]v$2#~#c.#u"2"!6!9o cCc؍fM΂lq}::w;`7Dj c`- W s ) ?_t_((gEX:_ J zZ.Y#A 2PLNݴ] ܴOٴ״~մ[ԴѴдʹ[̴J*ʴyǴ ƴHôg h* 浴{tį火1kE~X=-2ro-:胃}3{yt3o)rj4d_4FZV^PGJsFA W=F7 2o.'@"-94 B"cj cݳѳGʳjiEےazeL7L %nj ٰI*O}fLN{^챸q71u1Z22֌2k23((3̃=3*U3Nyg3m33QA3D3>3'L33033s3A334C{4@4/44j4vx$4*4p/4554:4U.@42E4K4P4xV4:[4 {`4;f4usl4p#r4v4|4tT444`p4 %44!Б4Y4Iʖ4ș4 4՞44$*4iG4%44)D4s44Q44ۭ44/44s4$4&4R4-448l4x344p4#X44P=4j 444#414v4u4b'444k4Dz5͆55>55G555= 5D 5. 5v| 5t 55}5555555{55Hh5$51Z5J5h5 5K5<55 5d 5]!5"5P#5K$56%5%5&5 '5K(5)5v*5V*5>+5+5,5nd-5o.5>.5/5֓051515z2525'O35] 4545555(55jB65p65+>7585Ds8585d95:4:5:5=:5;5m;5Cw<5<5 =5/=5­=5P=5n>5>5>5[J?5!b?5?5?5{c@5؇@5[@5T@5@5`A5A5A5PA5A5A5A5 A5BB5oA58B5OB5hGB5RB5/_B53B5&B54JB5B5A5fA5A5A5A5ɒA5eA5H.A5@5M@5T@5|@5U.@5?5j?5U_?5Y?5>5v>5/>5=5l=5=5<5^<5;5!e;5:5:5H9595nb95Z85+85A75[I7565<65#55R55B45=35535251515Dr05/5;/5U.5-5,5,5|+5n*5J*5i)5[(5ߠ'5&5&50%5g$5#5"5"5G!5w1 5<56I575u~55M5558t55[5"5555x555o 5Ic 5E 5 5" 55?55z5C5e[55557j4/4P<4M444p4u44q4uA4YK4֋4.44i4"4~4144T44k44#4N{44t4444 4L4k=4!f4a4K4/4X444z74>4~]4,4$4#14xC4ł4(43{y4gs43o4j4d4[x^4Z4T4N4+nJ4)D4>4Y9434ad.4 X)4K$44j4)K434 4y4333d33A33&3E3X3X3nj3~3ei3wS3\C?3@,3X3G83a2Q22:gI22="1԰xl3 eqmβ>(%5GDpXwn_}{DB7tW8$qȳгܦ׳s㳬s[@DZH`LOR"VDYY\V`8c[fsj.mcp>sUw$zs~~Ђfl >)䈴ߋ>繎WX0`!6QAى$ÙJOIRٝ:៴Q\{@8"ȥ ⧴/  XêΪHٹF୴Tׯ 簴~_opBaP]ܴŴQ1uIjB 97⒵97132SGζ,8`%:h~k%䳴8i䲴}\;~b>I*ubѬKꪴQ03G YiƤ죴ͣСH5☟蜴 N̘ ͖?%1tGWƑb͐Ug繎A\u%sXz2p1 ZX~|ywtzqjo3ol93jgbeXRcQ`[x^R[!X!-XF4U~R8PfLNTLJGEhBGf@=z;8 63{01 /؈,y*/'%j"- /ea4n~m ) x i?%LzR᳍ܳ6׳Gӳ̳~ɳ5xųi Wȶ笳@hvMznAY&Kunj {`XQ:HB׾7p/%.zC ye߲5ŲEԮV4 e3KfZHߣ#/ڱG8FJFJ009n-19n11?2527 W2]2ł2 ԕ2D2D 272#2282z2Wb3C 3x 3{3 ^!3"'3_13_33e<3A3K3M37 W3U3.a3tk3Wm3t3 bw3S3333o3G33^33<33C3}\383|3333۳3ִ3.33Cw33%3 3h3N3Z3(y33r333 P3433 3%333Z33P33F3L~3ݟ3=3k3)3p3o33+444444ˑ4 44)4=_ 4K' 4π 4y 4+v 4 4c44344[4'4S440/4n4 4z74{444"34p4u4244#48474Z44444 4;44LT 4i{!4n!4"42##4#4$*$4׎$46%4 %4&4&4gN&4oU'4='4zg(4(4)4])4o*4xp*4k +4+4V`+4k+4@,4l,4-4-4[-4-4z.4|/4K04/4L/404ZO/4041424Օ24 24604^>3444_34r34?44AL54qW54ĥ5464976454jB64p74i6464}[84?84-84948494N94)94c[:4:4ۭ;4m;4;:4 :4;4<4e<46v<4=4̃=4I*=4x>4r >4,?4y>4r >4?4%T?4$#@4V@4@4;@4@4AJA4bA4?QA4B4A48L4IL4=L4}ZL4L4ӚL4M4L4"L4"M4MM4"M4M4ġM4D N4WN4N4N4bN4(yN4N4N4XO4O4N4zeP4mN4.,O4*N4O4 P4^O4O4.O4OP4jO4zeP4zeP4_7O4lP4 P4zeP4vsP4IZP48P4{P48O45O4XO4kP4P44g=4 >4W<4;4<4;4D:4R:47:47s9484MP84{7484+o64354Q54V)4434I34\14Z14-14[04"/04Z/4o,.4-4^?-4+4q+4O*4<)4Q@(4(4D&4,&48&4$4*$4N#4 "4!!4O!4;4.4444؍41)441444_43E83Dr03p/3t'3; 33/3LY3: 3y3k2n22>2&N2/^2 ,202)K2E2!2'Gc2/Z2,,2֔22`1R:1cW1l0:gI05ŰT:`eyla V$<)j\Zz<xު7|2 .5  3UUg>(akN?r@0/ePF !2"(M#9#%gN&X$(0)*+x,I+hH.10g1<2d3,4 6p618Ȕ99@;q<;b=$?c>+@1AAECJDDmgEsFG3HjrIIGJwJ|LN~NMO^PP;aQP,hRR>TTaUqUV>V XXY;ZZ9[g[y\=\]ʇ]gG^i@^`m`Sc_ Ue|Y`۪b!b_gbb3bdZc,d:`eerOed9eelff9gFg g@g~h?hߚghh˵gh=hghhVixjDheiEhhpiZh/ihׅhhi>Oi hͯh2gh+h hhPgff\rfhf,gf:/fe,e;e"eec?cՎcm/bbbba(aOa `C`ϧ`^k]N]?]\d\[VX[-1[/ZY XuXXW'IWV*TTTQR'RXS:QP=O!NfLN7LKKiKˈIcHeHWYG3FE5xEnCB[@VAM@q>y>^V3_h33d3ɍ3S3333]3#3 3w3v3q333T{3,g383[33>3 333%3$38431P3f3g3g3343yc3W33[3MG3Р3333333l3(44_4S4tT4 4 Z44U44|4x4v44^w444$44K4|4/e444U4?&4444m444ð44=4+414m393 33E33%333x3O 33R3!32333Sb3933.3x3*33W363>O3¨3֌3vo3r3J3.3,33!3j323 333m3U^33s3(y333p333.c3]3\C33O303{3333=]333X3I+3%333͡3-3ȝ33֗33/3Α33܌33D3G83_3€3~33q3ɽh3Kj3]e3g3d[3V3 P3FJ35E31A3>3)93_33+3oc%3h$3Ǜ3733 3X332t22*2ze2q22d(2נ2賖2{i2p21S2A2a,2421Z1<1T18u1T0Ѱ6>`Ҝˊͱa"'EXXZhx Y笲߶fLβܲt>ު !d&p]-32"7I*=qH~IXOTE_֋` iuur{:;cȄ]Rډ ؐ][ sN`9N֓ʷָ:|³ήijIdzPɳ˳ гҳ>ֳXسڳK޳]1곹1tS"ûtmHiq?#1π ) y x c/vH&SMl ]X/ R![!F#b$%'E')ٹ+V,Ѥ,B.h//KV0Q1ix3U04O567MP8E;9k:m;[<=4M>>@?؇@]BRBgCEVEF_H3HtHI0JJ1KiCLL KMxNCO,PPOPQRiSTT,UUTVcWWWXYZ["[[T\\j\j\]]^G^^._!`a>`aaa`=$bbCbbm/b!bbeccscc,d ccBude d=ccchcyc#$dcjdQnccjd=<ۭ;!:$9}87 6,54_3'2L1 0/2-/,R=,k*y)zg(t'E &6%p""4 .4Ca XXjE|X%#2qH h  \͈f/b$kQNO|>Ol {3ݳ]<۳4FڳjԳҳm0γb]ʳ ɳXų³ sQḳiෳ=]LwAk=Rq&s랳w Iʖ4i⏳.2[ )' xqbgP=d_fXvRKSjC=[8ϯ0*~# ~kN.ٲԲ Ʋ<ĻcƬ ^M]Kun_A$ $\ʱ6XOHܰ /11+1m1T2q2:2[2lf2q2賖2̘222222\ 2F2f3Z3i3F3z3 3+313w73$#@3F3IG3O3ɍU3]3g3,o3Tr3ACy3*|3_3̈́3833KŽ333_3E33Y3oc3 3%3 33ϳ33q#3ɻ33r3KU33?3h33t33A3(363t3o3T333ٰ3333t3?3o4tT44y44J44u4Y 4J 4 4! 4,q4s4B4a4g444-4A4 44.h4?4uM4K44s 4!48#4 #4$41%4A&4zg(4(4Ơ)4d(+4*4+4z.4.4L/4/4u}04C242444?44AL544464984874094ΰ84:4f;45<4=4!=4G>4>49?4D@4[@4A4]B40'C4uC4JD4XD4~D4E4E4F4&NG4H4?PG4:gI4tJ4XI4I4~J4}K4vK4pL4uL4 KM4?M4tN4M4N4mN4 N4 3P4lO4O4IP4FhP4P4Q4R4Q43R4AR4xR4 R4R4HQ44+==4<4;4!:4t:4h94@94}[84874~6464Y5444443424f24 04@/4e/41Y.4.4Z.4'-4+4B+4h)4̈́)40%4'4I+)4$4)%4#4!i#4'!40 4 4Hg4 l4 "4o4#a4_4tO4tP4Q4D4;44W444#4$+44@4 4H 4( 43 4K 44[Q44;4q4 44<4D3@33,3s33R3*363=3P 33)3,373K3d33׻333MM3w33a33!33-3-33R3¸3 3w33Z33火33Sӥ3H13נ3D3L33i3n3a3r33o3ɉ33j{33'3v=}34x3Tm3wn3n3#i3qd3H[3 PY3jS3O3&K3F3$XC3@3Cw<3yl43P03hH.3{'3A4!3H1!3xs3W3b3zn 3 3343Z22|Y22?252 22 22 22 2h2{2x2\2`M2>2?!.222;21j1Y1_1'710nj0_Y& F8uylzeб; Ky5֓0S3LJU_l}Da録r⨲kNALaŲ<+ƲXϲڲ%۲:Ⲿ岨CY&4N & >(!N!"-$&+N.&225K78Y?=>GB)E3Ib]JLqRXO~TT|WVWj\?^ 'bPbafvoh8i{^lƗm nr.*wgsm_u@zF{b{}vAu<r-ӌgznM9 m0􌳲ڄ% .ߍ QwatOMRΑҔZБ5BꕳCy*ݔyՖW[$ÙB#Qb#4dP*v*ٺ Ɨ8hLțk {z7Q؍R^;{"gPmѓ򌒳211i⏳ّ+AP7L;?[戳ު[Q2[9?cBłt낳j(@~S}nx@z5?vtkvs@oYptl~kgYh.cLgn`^?]lfYW.UΓP.QQP֌L1KHGGf@hBAJ},;$\=n:gɱ֧ ԕ T,hv wxl30ê0*1-H1/Z1xs1g1q1J1t1X212X2="22uC2@J20WV2PY2\s2Zh2t|2+2q252*v22 22F2822h2\2 2222:`22u2Z2{i3B3(@2` 3U3' 33q3j3[3F3L3 "3ߣ#3$3sR)3_n*3C23:4383553#83>3?3%D3EC31K3F3>VM3O3S3KW3[3H\3^3Sd3b3Yh3Uf3Yh3m3n32 2M2(@1EԮ1F11Q?1C1 F1QA1$#@18u10^0n/D:`e :t||ٱӱS3̱"E,,)@8L bUnwK'P۴K& "n~{27z˻(JձౝAƱ<ߣC9n錱(11Ŵ1@111?!112Z12[2V1ު22`2F2 2O}222`#2ˊ!2ߣ#2o&2yl42<2j;2#82`M2 I2HC2;P2 %R2Oa2E_2cp2q2Jc2P=d2m2Qk21Pr2}2y2|2i~2CI2'2ު2 e2=2K'2y22K2222E2݋22}22mѓ2_2ى2&22-:22Q2 2W[2G2s22׎2M2wA2!f22]u2|22q2h2y2u222ƨ22]u22@2֧2F222#2H2ad292#2'222N2M22'2v2z62:22wA2L2L2j۫2U2@R2J\2h2y2Y2:2P22Q2 2У202Q212;22u}22YU2a͞2/e2wڢ2#2N2L2JĞ2h2yn2222$222Sl2s2k 2F28u2V2՚2Eے2戏2 2\|2T22=_2ڻ2ӄ2U242.l2}2D2>s2D~2!2Lg2tk2ׅh2*o2b2:`e24d2Kj2b2cW2>T2&K2 S2,?2sJ2J2eH272>2|@2q826>2Cw<2t:2!12͵(2/2 (2;2͵(222 22eZ2;2"1s1a11^5111=1{1#11>1z1411ˊ131ś131Ax119.z1*11E1yl41F01k 0D/m0T/ 0="0n^(ߣ=AZT,<)}-4qf{*^뷱p\龱ya鱨Csϱ\!2+.e '3. (,< /y55H1!:e!GMKkGfLNL`L\|re1Prt|*ownmy~Ty=RvHhakؑ,ؘ8ÚVKN*ݤ6ҭ>9n)EԮ4泲۳ kἲ࿲6\Cмc^nƲ:gɲ*=˲Eɲ4Dz* ̲hzѲ~ӲݲvԲJ#ٲNݲڲײ7 ײϧ_gⲤⲟe}"H(岇kC C!clA@f_Wʔn tTvAƢ( 9a R I2 X ) s f!}GI J,ܯsl>5 uaiIw~ ,zi?R Jì[}x($ .F!B~ ڃ 9'PXoqKq l:i!K ~"fDB~#|K;`q'""!eY#yIJqttY Pݽ ,4泲d(zZ Ģ/e0𑞲ˊr˿#4vHMRXD ڻׇWb3{yUy1Prew. b8hZ0WV/Z;PO(D#(L<;|&)9Dߣ#R:0͵('a,|&q T QA !Ny籁kfLαֱԱJȱ~Pݽt$t.c`M]_18uj;+?!.*ﰹjS3̰8u6/?:gɯ(/0S3L09n-0 00QA10D1"'19#151wn1:1,o1g1]E1֓1̘11h~1X1C11r11t11#1*11f212z2 22;21)22Q 22Cw<22,2-2j+2=2(2Cw<2F12vB2MK2vB2P2ZH2a+_2=W2Q2a^2Ya2wn2sc2m2/Z2t2t|2wn2S26z2ł2xC2ł22n2n2l222ì2Eے222BN2s2]22l22Q2+s22]2<2o2vx2EԮ2%U2Ԧ2]u2O2 222J22*22ջ20'2Uǵ2훶22 W2c2>22sQ2^n22|2ˈ2s2z2W222fL22~2522;2ze2e2j27 2hw2u2Y22) 22k2z.2$2M22#X22B2242'G2f2.2L22|22'2~2!2 2NB22k222x2=2f2B22M2C>22jj22!2(2t2%222Pm2n3.*2IX222Ȏ2Ĝ222x2_322I2+f22U2r3222363}2_3 e33{2!3(3'2E2Р262222B3y33η32"2A2S2=3x2'2Q33tT32qN2<333U43R2"229.2``2g22/22v2Z222z2A2I2Pm222Z2Р2Z2u2<2G2Y2ut2ř22Z2v222>2y2O 22222y21P2 222@2-a2[222;2Q2222b2>22 2]2E2@2l22\22_g22:2]2H222A22.+2!2qU2j22H_22d222{+222t{2227 22O2~2`2q2I2l2g2|)22c2222L22a2A2+2>22212߶2%2_2|2Pݽ2ĥ2߶2N2.2(2|2/^2g2fS2.2L22+22}[2r22&2E2:2|ɦ22h29֣2/.222Q2h2d2&2]22q22,2ś21)2g222z2n2K2좚2W2@2M2t2b͐2G2h2 2L2v2j{2C2;҃2.2ˑ2_2{Њ222x2A2_2X2 bw2Qu2y262G2~2A|26pu2 p2xo2t2Bh2 bw2/s2e2Zh2e2/%k2r2{^l2.c2PY2_2^P2Ra2BEQ2:b2j\2V2mV2hB2L2[2*U2uC2C2p\A2L2FJ2sJ2<272?2 D252s<252_12/^:2-/2yl42*2H*272/(2(2(2-/242W)2L/2ˊ!2n2U22"2=&2Q 2,&2q2?22!f'2!2-2h24O2o22$\2E2f2= 2-:22 "2< 2 22 211 2v1x2G82O221!2A212q22Z1(@1'1*1>111G11 2(1 +1'1^511A111Q11Ş1s111(y11м111O1ܦ1]1951z10W1J#1KS1Z1111)1>1(111J#1111T,1A1.11K1Z111|1J#1v1-11׾1i11-131a1151`11J#1o*1111n1ـ1"11Pݽ11)1 %1fS1a˸1&N1r1311ze10W1Y11-1u1F1~1111~111!1*1s1+1,h1:1@J14111911l11#1n1_g1VW1C121.111u1'1ׅ1!1:`1t{1!2n1'1 221'112Ƣ2l 21(@1 216J 2R2@2'2G82"16J 2D2z2?Y22o 2k 2 22.22o 2#12V 2!232>(2Q 2_22k 2222 2D2222xs2]2?2R1E2*2/e242=]1224422o&2h$2= 2[82z72z2%U+2+22 02r(2v2_(2 4<2*2';252'22@?2/2<2zG2<2i@2-H29762֎@242g~92@2E2~I2~I2gC2~$A2J2aE2C25E2QE2OR25O20J2W2?292p?2;P2\I2P Q2&NG2 D2K2:`e2Q2Dr02mN2J28T2uV2zeP2U2k]2GJ2!b2J#Y2FJ2i2.,O2|W2|Y2*=K2`2[2|Y2[2m2qH2<;24f2H_\2.c2a2Si20`24d28i2]<[2q2jd2 i2_l2l2|2Zh2g2m2ai2y2a2Uv2m}28i2rn2p2ew2y2em2y3e2y2|r2o2^5w2n2=u2i[2Lg2ZFs2 b2 2On2v2(v2Xv2{22y2ew2'}21Pr2*|2w2n2 Iu2-an2t2@z2w2ipq2q2~2q2z2'}2Ҧ2X28y2y2 x2u2"~2f2wn2uu2qNy2܂2w2r252~2_ـ22|z2:{23~22CI2O~2P22r2{u2]2lf2x2.2\s2-2]ln2z2y23{y2y2wx2o|2S2kv20|2Ho2q2>s2*o2>s2d2nj2!b2a^2xz2f2aE2b2/%k2lM2Sd2DpX2]2 Y2`X2:`e2U2.T2WZ28P2`2/Z2Z2T2i@2rQ2SK2L2 I2<2~R2p?2hB2dQ2oK2BF2U(d2T2Z)2>2O@2(2A2?2ڂ422;2kD2?!.2y5262d(+2';2}-22"2c52%2d(+2-/2&20%2wA-2:22Y02 '2|2o22w#22`1 22<2S 2G22 22h2F2o2~2#12z221p#1ѫ2% 2-2K22i1(@11r2t1l?2g211>11d1a1:g1411)1&11P11E1'1ǭ1Y1,119n1h1d111W©1L11Ǜ1Sl1>1t11J1OP1Q1/1w1/\b15O1a1L1;҃1u\1rQ1 c19n-1/Z1.a1l31H1!1"'1o&1X1"00-0{^08u1}0d0 I030F0$0gE0ҵ0kt0o0݋06>0(v.Pݽ0T/~R0cp0'/uu//Z_1CmNn9nذҵު̰Z F\s\s龰DivI?4P8/"m=WL/J#YcW^:`e"[QުqOME_ҐqocM7Dʿ֧֓N뷱ű?!$W$"ȱ&rٱEԮuẔб"uձ]<۱aޱl71P/8//-6* 04/^:-=;76-H/N6Gy>C/D=6F7C&NG(yNAxI09x>(yNLK]<[!`(]mNsO-H֌LS3\UY%\&KRa] {`/%k(lZaaA_a@fhg]cC>mpQsea bzdja PYӖdAx#iq{^lg]Di}"i8h6k j Iuhdonxo$zKuAxXv@zVWo{^l bwnq"X{׵{Ut|łqNyٍS'KH{Quyւ@€ބ"~yq;҃~CI~wᆲ ) )̏cȄUy)䈲Cኲ\gcȄ}즂qꮊ6胲5ІyłWbf3a'yˑDwᆲ.0Puˆ󇆲k/΀RډރÉT[Q&ȋ}tT.lnj eAc €ԅ抲=p.$p.)䈲$ȯ+tTDxtZ|N]|~>sXU€wᆲ};jwᆲCI)Gl? ՁڻB!y bw5fr?}l?Р|Y1PrCq^5w!y ):{g{q]tqNy``~$Q{{ZqڻUntmgt|rXvXvYhb${-xntm!b3m7ne_XlgKjOntg\o%f2gmojd#X_Do1i[q`scXgXvjcpeWuDa7:jc2Ts[gj\|r95^R[u\fXVd~RPQnUL_DpX}^?ThwU{PfLNmNEV:u\]5ErQdGM9SjC?@=ECR:ZH@ɍUdQJUQRMP$JFj;P%)$9W<;lm=[@^2dG8B^GM= @F7 AqVI=>i@AMP8#. .976̃=] H_3=t:G:6<\E/Dz.y5Rq'S%%,R=,֓0'PE!y56'+(0#(j+V$H1!=]1="!, "%G!gh$oc%i#z~&rC W[R!̼ ELc/TFN,qg= .$\M+< ՚}+;k~ұfIA۱ܦױ4 +]Xyjܱ6J :gɱBKV0/e8 LAL b!x_7ϱ G -@p\?ޱ۱C>ƗYe!DZwޱűyl2ݱϱOOmαfLα-ȱwޱʱpϱHñ/ı|±űF4ձ۱;бϱBƱر>±- ɱgMlDZzDZd۱*ձ/ڱ ̃rѱrѱͱv±-ȱsϱƱ׹*ձձ*=˱ %ұު6/ڱ_6DZlyzىKe#e*㩱ǛH7C+ǔ֓瓱~&@֗v㨱𑞱៱N녱5xsˑ,qv 8u,՚ g!bvH錱*Eg./Zzvf z95^Mښh4a?qQA+赱 ԕnjaűՎi⏱dz70ˑeZD,7ܛJ\^On]tFJ_Q"~[_njCq3~錱x>(;!bv.ã=♋'}wt|>p%uM2N녱WZ]xNygު\)e~njtJ#Y!b*oXρuIeTo%Zz'}Q$pZhhBG8;҃\stkwn.acˑy1Pr'}`M€]enj DUl3 QagEj$Q{S)~R"uu<'Gc.33;}IZhp"l_j;̃=a^֓0>B}-l3ׅhcW'}1awn.ac/U"'SGX fLNY0ˑr35>(,! %878y* W=q,_]mDitRaZzAFcW )_@JzeP1S7p5'Sz. FVl3>2,ߣ# q D.c9n-6 !1fa7vB4 E8MKcװz.]Jհ= aްXZ`Ͱ4DF_-?!.z{ gExs%U+R:6)$\DI*aް1_fS2sϰ_9nh° ߣ#ˊ!̃Y]ܴrѰn/8uٙٙ9n\s?5EےZ䗰uðxVWˑcװFʰ :Do:gI nͬlm CCмѰٙ6:`e5Eq݋ .aذ\s1S6_"~QA_!t 1S(vDa \Y(vկ(v8ul3賖T,am %֧D /ZHU ݋QA:gɮ %8u/ Ư/֧./6>0o0l36>00!b0lQA߮?00mN0D/ˑ0N1a0y0./l/10!b0cW0'/S11V0<0ߣ/w18u.f0<̋0*o0,0/Z0X1X00l3/C0Z00{^0 0G00mN08u0X0c0\0Y00C 1ҵ0Z00r00BE0|0BE0r0(0 1r1 1n0T,0D1T1?1r1 (11?0~&10_00a0:141-0A1+1<)110c?1J\(1A01G811$ 17C&1nj 106J 1*1 /1=1 1V>11 11$\1o+B17p1[1+10~I1j g1֓01ˊ!11'1=1|Y1%1]1r318i1E;91)L1/΀11sO1_1]1V1qU]1~z1O@1>s11Za1!141(l1t1'Gc1v1T1+1rZ1!-X1̈́1Qk1A1G81T17p1P1e1\s1cp14I1k1_1l11"~121}^1\1&11ˑ1e151z719n1o1/1̏1U1C1u1Vɍ111>(1+1Eے1O11p^1݋11䍛1i1I1Uc141mo1w1ԅ1101Ƌ1}[1{11$1נ1 11՚1S1<1B1@1n1|1֗11 1;˟1V1Sl11Ħ1H1~1P1~11~11|1/1'P1o11k11o1q1_121R:1F1C181%U1 1ҵ111ߦ1f1s11^11Cw1 1Ş11/1Ǚ1<Ļ111E11 1141^1Pݽ161Ѩ1P1C111ٙ1ҵ1fL11F101Q1"1}1ҵ1R11E1E11111>11fS1N1ϳ1/^1&11ȓ11I*1)11)1!ͱ1ad1*=1a+1fL1j1K1u1cV1Te1Pݽ1м1?1I*1p%111]11111S1X11#1q1m1[1&11115111u11:1KU111n1r1c11?1h1Gζ1>1j1V1O11s11cV1F41111`11121P=11H1ϧ11q11P17 1Q11=111V1d111Y1qU1 {1 %1i11311c111%11D131G1W1c1S1Ց1`1.1d11+o11S1Ց1.,1111+12111/^1M111611i11111r1#1H11'G1t1,1Ny111F17 18<111h1k11r1A11a1֌1 111fL11E1F11`1m11%1161O1b1C111/^1p1s1Qo1a1a1H1 1|141̃1111s111֌111"1X1x:171151H1Rh1S111r1'G1S1X1S211j1v1X1m10W18<1P=111~1{1^111ή1E2b$1B1 11s11֧1E1<11>1f11k;1?1p1=111A1qU1ߣ1j1a1A11h111@111~1b111"1 1i1~1 11B1֓111Y11d(1ɿ1(151:1p11q1EԮ1v1K1111D11 1ҵ11Z111%1111:`e1n1)1h111π1Ϛ1i111161f111π11$\1a˸1[161n11Q1͵1t111I1nj1$\1K1 111N1"1i1ƕ1m81nʯ1(1xێ11/111 W1נ1Α1v1)1QA1F1Q1֗1ˊ1H1117 1}1*ݤ1y11B1H111g11L1(1I11z1(1/11'1_1ì1.1+111|1k 1ǭ1oc1R:1C1N1"1}1y16J1 111ew1͈1111{i1%11r11U1z1̼1)1oc1~1611SK1ݔ111>(1g11CI1B1Α111r18s1~&1՚1r117p1[1{1_1qNy11̘121U1a1_1?1.1L11s101Ƌ1)1T113U1z1`ք1S}1 Iu1p1wn1Zh1Qk1a1eh1{1*o13H1'1~1|1lf1zG1p1&x14d1m11{^l11[1Fm1s1R1ei1Ax1l1?1iK1nj 1/^:1o1.1r1H1 N1a11=21U11qU]1[1\Z17.1a2C1@S1y1C10O'1D1e1[1 1-H1)11km15#1YV1)1Վ1\s1@f1+1a,1xz1 D1uV1I1l1dF1Z1i1PI1BF1©U1O1n1t1P1j\1]u*13T"1a,1"0qU]1yG18i1e1p161X1ߣ#1{^0D1-1yZ1U]1 0ì1/W1)1e1x>1y0B1.1Ơ0N1+@1 >1O11I"1L1171z1,1uV1"'1ڂ41 .1b$1 51a,1-1_31A1$ 151ze0G51h)1|B1 F1A1c>1B1G81C 1f0k011{71 1r03+1m;1h)1R:011Z051%11) 1 1$91i1 018 10L0 2111r31110$ 10h$11U1M1j19n-1>000*o0Gf0CX040A00h1a0 %000_01!01ު140(1Р0d 1S%1(00="0C0K1(0eZ0"'1:`0LS00a00Eے02[1s0Z0 1T,00=1uM17 1M1O0001{0:`0400S0 %00 0(10Gf0Eے0ׅ0z0m0T100>(0|0{/x0՚0$\06J0Q0m0k 1/Z0{0)0(v/Sl0$00800֓04d020j0}0|00QAt0m00cW0{/00zeP0?0a^0T/T0м00ު16/0eZ00A0x#1/Z09n-0mί=0.:00c/ 1_.00H 0)f02,0ҵ/x/Z/010)0r30(v/Ny0r0/q0q01S00e0Zz/{.<0j/8.G/y0 ^/o&0D/ 00/r309n-D0K0/6>/10l.S3L0S3/ު*o0N0 0//l30/K/o/ G8CQA/:gɮ_.Ax+/eZxs(v/گ(v.򛯕u9nl3-R:07 k j*8uA:gɮ.mNX/+^l3-t0mNqr,,AQ:gɮQ݋jxsD.8G0(/unmίTl3.ބ i߭A66>T,诇mބqU]_-_=&*Uм [Q"}Uު_H11SJU >:D6հo&֌L ֧(ðQAY6>ð(v/Dxe{^l,="E.(#BEѰ&xEԮsϰ.cd۰SA_1\J^VTc~k n갥>̰J#ٰK *ﰴttsϰ5ŰtC֓0尛O'GM˰4"𑞰߯t방̃{^ Ű՚.o+(@ g_q,`.㰞Fʰ\J#H*%Uߣ#v-Ȱ&vH&.-(k  ư .l>(" [Q+հRB&ָs _N C h$i@_1g-?!.AakK&xO!a뷰KO\J#tĥ5F vB#9n-&"'-S3LZHj;.afE 87,,U"_31v R:0"hB`Mc4 IC(6Y0A4fS2E3Ho&:)C +=]1iLrh$MK @ʰ̃=j; I>(6W';&Q4g~9~z>AL5%hBAF°$uCh9$ˊ!*U1Nߣ#vHei$J@"j"66>A$\^t:j;JU&NGqU]۰EQ9HCGf@@-k SdQAl3(_3]u*]<[S3LC %U+n1:HCzG*o-/K4T]<[LN`NK,?{p$#@~A:0RG7C&ai5Rbr38h 1*Gf2&2N-/\s6>!b6Af"ˑt;҃|Yˆ!۰7Vw^|Y+E:gI5EZe!GsO {`rQo&C>mF1z.|}^*U F5'2D\C?xJ<1l5E{;lc|&,&‱JhX=;}"ifnDpP bw>4uu]VlhBZLOn__1buC1A\ZF 0.~zZsJPYd[W-Af]"~}b^8ia~zw[j\ʊJ#Y>sCw<{M`L DuCXpM%:gI=iI6>1#Tp-)9n3w OT,hoc:gICwXwA-_p7=2ƷC@E.#8?~R` (x(vD09 KQC>mXLN5EQh$ D'hB#8zGb-:KUDxsi^5s1>J(!b[7 W%4b5 W>M>RasIm{7ZH I%U+~$AN9<)-/<;tIZPO9Hq!1Kuߣ#7C&7O@eZuCj+ ZfS#.$#@`Q*U\zr3Q9\J#:`$\T,hCg4g6A7s9ְ.cFE(p?̃=QAxCol 60QoOqiG&PD Q9~R&*y5vHְ+(>(r}ްׇ៰~I~&O'w6cװqðntG8U.S+Ѱ[Q#鰌#&Kׅ谽ɰ7۰^ >(<)WbKl㰏Bϰ+c/ְ ư/ڰc?F-Q|̰}ް$\yl o.*! 0 аrcװߣ#̰1Pު5$\a J'1p1ذÉުU"QuðTGgFذ'8 ,6ܰvɍհDN녰6>OEے=") ;ðyś{iР@ڰPݽ"аˑtRư OŰ MҵcװY/AY&]ǭ.Z̰ҝȰ6`HܰҵaްG8qð_.Eے֧gE^ =ðTܰ:gɰ ߶C qTzǰ m {5Ua(İ賖Nu&ˑp*հqNymNhyKutl,2## ǃM$H\P Α AgE"ބ՚FJ.c/=nj/A݋;߯r)k Cc/ śAwCvEa^֓[Ny"~kǰh?M_.$\2ԯ:gIx ~ (T,诒?(v.:͵Xb\J{^l瓰/Z/DDxsZ4ew KvGׯܮll-;Z>s֧!bD-)hBF~l?q-/(ݯ~&)2Ԯ8u 0{ /t|.+cW.zePl/:`QA/j;D..?(@/l3{{D=fS2l3.8u.?0CqH1 K/4`ͯl3.@J./_1*xs/~QA/{u_/./ï.njr<נ//p/0߭[Q/l/ /߭9n-.\,/C0 A/߮=0:g-8C/l-/Sl3./o&0 Я/ Fl3/m0D:gI0F0_00*U0 .Ɨm.fS2/q0;˟0:gI.V//v ު0Q8u.k .:gIk 𮡐𯞬0(v"/6/6>k 0.a/ 0;07/90(v:`e/8/ 0Pߕ0Gf0./$0;1^5/!0l/.eZ09n-'0:`/0r30-H0H\0OR!b0H+0) 0w0'/1.̃0:0O0a^0&00s040eZ0&N00 1@J00y0G0$0Yh031]<[00*0 e0Cw0~1MG|0&hBxy0ބ0o*0&1l0ImM1C 01+09n/t|0R:01ҵ/10ZL0$0oc0D.t0Q0 0{Њ0a,100S0ή00$\10+050>0p10S00W"0v0o0d(0.0#81EԮ0a0q0ai070!0r0p0(000b#080m801S060q051yl40v 1Uv0//MG0L0Z0@0&0Qu0lf0賖0H10O1n.fL011.{^l000 007000\1Ǜ1훶00ބ0?!020ˑ1yl00w0(@0 1x00^50O0O0Ax0~$19S0w060_0X0,,01#1Ny00fL0V0QA0^0H0"0_1A0%00 PY0E0̃006>0i0gEj0Q0 0?!0&N050Q0戏0f0(0D00000k40T,h0{^l01}001f00(0*=0210;1/e0̃0="1:gɮg1^1V0_10Z0@0f1^50 0ބ0-00nj 141֌0&1E0800 00u&1p\04En040Z0t0$1 0?!.0q0O0qN0(y0{i1oc0Eے0160 1 1e0r0-00040_0~R00+1?0050 ,00K0$1)00j01E001)00eZ0_10É0:0J11l00fS0w0Q0w0F0sS0 101-:1300֌L00U0m81 %1Y111s00-0U0Ş0(@0<Ļ011,0p\00)00֊0w0.00t00k400j0!0[0N051q0Qx 1ׅ0D. 10(0060S0e 1(@0$\000!0n_0功0B~000U0$*$1(y0000ze0ǭ0/0C 1鬲01 0` 1Ī 1 0Y&1 }0uu01@0*o0Y0-00\0!b00 11(1110#0030'0n10\0*0$10,0L0001u0 0-0 ԕ0gx0<Ļ0 b0s0Y040tT1G1jB0S3L0019n0R:00r0Q0>0R:010/-1x11P0j:0Y&1r1(0x1ު0l0h0@0賖0wn0n1м00 0?!0%U080R0z1( 1xz0 D08u0'Gc041l0$*060 0^n010i0ˆ0 /:0/e0Z0 0U00f000A00>0%0,0`M00 100H10Ŵ0n0e0׹0Ic 100a0Q01 0i0`0qU01@0nʯ0J#Y0sO0 0y0C0p0_0N00 0{01000 1?!.0У0?!00:0 "0[1 0K0fS00 (0t0&01՚1600 1U000+0}0)10c0ݟ00N10fL0 0Nq0m051ݘ0Z0I0|00L00K0/a%1fS21-10>s0j;0+0݋00}070.a00<0!0ze/n1CH1c?0"10Cw0K00rY0!0Y&0r0ҵ00 (0r30b0k 0m0?!0YV1:00ު0 000G0݋/00Qu00qN000400u0xs0ڍ0s000?0yl0,0\0u0Z0MK0X000_0?0QA00ҵ0ˊ!00 1#10֓00;0xs0:gI.9n/É0 i0dG0 bw00)0$Z0j0=8u/ 0S0X0<)0|0Y0f0xs0OM0ޝ/Te70{˶0A00_0=0m00fS00r0ބ0ɿ0g0}0ʐ0/`0}0'}60ުC0eZ0/Р|0z0Q0 0e00Gg0 P0a087/ FT0.0)0h/.?0@J00r0/0賖0߶0T,/{0t/I"0w0Ŵ0`M0o&0v 0?!0T,h0600(v0w0C0Ѭ00J0L00/h/5/?0"'0X0_ـ0l300x0O@0Р|0[0mx01ު0/!0/a/r30q0//0:06;0!0՚0W/0H10 /נ00>0/ 0ߣ#0~R0t0.A0+0qU.0Jn0K0g060t060m0X0H\00//.ߣ#0~&0k X0<00gEj0l30O0-/0v 0x0X/z0l/.0?0?M0~&K0"~0:g.<)05E0.0 /3H0:`.C.a/\J/0(080:gI~&0/QA/0x0X0../,/Yh0h/0,N0 >0 /$\0+0֌L0f0_ـ0ٙ/(v)0l/a/<0q0_0nj/̃=0̃=08/q0 07 W0D-ok /r0\J0.0ˊ0/̃=0AF06H/60C0l/.a;҃Kگxs..0S3L/r0/0="0 /C<)4/Wb0I0gEj//V088u/0//.U0.{^l/~0r09n/6p/'0⨯N/߮ I0r0&K0/ҵ/0/*o/nj1/i(vj'/k 0&0S /;//c׮q/0;/[/I*//(cW e05ů^ %.)n.9n/м//D/C/𮠗T F//[Q0iS/+Zh///e/`/{//_n.>mNT,/ߣ r0-Ϊ/Z/l-nj(vE?0ԯ/l- ,/?!.|ɦy>S._.k /__1/0WV0:g.9n-0-ٙ/ 0/ZC0"0k//R:0/x/*/D.}q/rQ/(v ߭𑞰rd/S|u&"~v8u.x0V/sϯ .̃/Z0~ɰ&NG0tw/{11:.'eZ0S0q'"H"~?.87/C 0*o06/{z.@zj;/1ӯ9n-/k ~R6//DAF/%U/0sXXE/>s0C/N]ު0:gID?bA;03`Ͱ.oc%%ܯXf074df_6QWXmί/%k/火/龯fS:?xo-_.X/4{^lQAyl/OXv:g-t//G8v.&NGJ/.D-Ӱxs/ٙ:`eh龯.c/O戏8u,HïM˯lfY0X:g.U"S3L+D- KNgw/߯k pۮ3A/D.H1!Qu"3fLίk /oS3L"~ w&NG10=l3Q9ł:`Xm6lބM5/֯D/!?!/&NG5/D.gE.u g1S QEԮ EhZh(ޝ*ΑALCw<ƤSay7prѰR:0R:0_68<° Ưl?!.(0505/. %<,,P=(7)qNy_ Ql.\s/Z!b Α аa^.ᯌ(@V$̃=a^-4]n?0  m&NGe#e"8^6>=]ǰ߯(/Z0ު9.l.ZH"~m$ ֯Pٯ&7C(veA氃uð;˟FʯΑˑ}7lS3L8&۴1ӯ]1ӯ?TeZ0Oۊ-uu?aE/(}^,,/?t֓0.Dw//x//,T,/X$ gDG8/}^rEےE %?!nj ?4R:0tkXc׭Mt\s0_1'S3̯2CwBud/腰[0hB-Af+ˑ:`e/Ǜ9/xs0nj /(v/QArM.) 0Α\0sϯ!D-Α0r0V$70:`l3) 2/I~ ; (ɰS-Hf|}98 60j=J\0 105E0X/мai0f10$ڱ,I1wA-0*|°MQu0Cyy09.zKUD끱"@oG:.(՚0[԰ư^K060EԮ.|Y0m80K0P0/ /]0:`0 W0n1ł0/90<0.0:b0:bg030!0Q/|s/Y&/]/(y0^S3.X/:gI/)rj{.wt #T/c3 xհS3L.71IHܮ~κ0l306. /l30,1DpذLXew8鰮h {௩G(m.C /QA0C06>x1/00_<0C0ś0m0yl/e00nj 0x0:b0F0T-ˆ0|)/:/|_@ 0f/T0l3-G8Eے %=/o*V|ٯ(@mZh nj 0/7ܛC.c_gO/ͯ*G8/y5/_,ze.v0!0/ 0D.(vx0DRǛ=W/3=W0C.S3̯k0w/X0ï:g-C~ҮT2M0fc0wA0FJ0:gɯK0njQ/q.0;)K0B1E000r0=0\s/(%U+0:0)'20n08im8/&N//^:0ބ[Q0_uuFJ0CZzylnj0+/ .cW/}0&d0".0B30(#Ic ǰt| _1 /<)|&:4// 0D+>) `) `fS2-Ȯ 0)0D/|0870M0. IL/l/~0o/м//+-10֓/i1Lg0~/-/1rm..#00~0l30Eےw0+A/l3-a.ˑ/T/Q9TmNlDq\C?00K/08u/v//_10ު0?/j;0'0U.0S3̯87/^/K0yl40D0:`宷xުl39n-05ů4d0݋V5O0mNr/+K0Vɍ00R:0/ 0&01S/[0/.aٰEے.60(@/)90Z/$\0T/ /zeP/x0>T0߭/_6>ryl4/|ɦ.r/C2O/x.P=/F1/0/k /2/.x0נ/0,,00o/V0]0/n,$#@0.l0 (0A8oc%03H0MG6n1/[80î?/j;/߯ F/<0\X8u+/I/֌L_- į[cW//9n-.QA$0h/nj/%U+0Qk0t/'Gc0Z/h.0U/008s0m/$ 0N0/04/l0(0|Y0V/ga0k 0L/00%U+0c/0/Z.kx0p\A0(0K0/0?!080D0R:/﩯i0Dpد4./.l C 8/R:0 0-/^8u.k G/h!u {^l/t/n1:c/+-0Z@(:`寓8/C0#T.a60/\s /k /l3ߚg0EC0&N0'20/ڭa^nj rb#010Z/yl40/.aD87//V$0Ax0:g/ZH0V?0NL/r30+0D0n.G80<Ļ090.fL//8uś6//ZNy/x/o)/D.̃=;0'T,0( /j"{^l/l0o*֯8u.a^/zeP}^0ze/l30o0_0a0bA0Nz0 0}0Z/>(0?0+/Xv0-//P)"0op0S3Lf`0x ˊj.cp^5):gɭ0FJ0QE0o>0(v -R0;˟R:0/Z/J/{^l/x0S0(]0/a0/D,ܮa^X̃_/.נ/!b//z0a2/K0.I*0h$/A0a40>0Sl0.D/-L0 F/c0,/C8u0-*0yF0Ya0.(0/,/p_0QŞQ0J#/S3Lk V+0:g-:gI0+|}05EZ/0k /nj0 mN/(0Ax?0!1j"0(0./ -00݋/!⮒|戏0w-qN/0WV0V0g0tr0.c/+w0/%/z0(É/n10<0G8a^.0l.hB/ԯ./j;.x0/.Q 0&NGAL0h¯"~/rބ6 FN녰{/vn0P=0U^S~&/x/݋0EԮa/'}X/ 0wne!Gd?/.33/0q'";$p@JhB.l 0/'2;/fn//|*9A/40E.o.0wڢ-0 {`y5/&2qeZ08/ (/"0=aMw0˭\ZyR:/O.00.>B05E/!֧.e0T,讟8a^0 /(0Eے/,/~&/կ3./($ /?!/fS2l֧m."/}/0{,/?!.0_/ٙ/nj {்,0î$\Ɨ/?E(c.8uV,,JU0_1/AqKd[II뷯?"!0QA0qᗳ0nd(+0-(v+_1(6/֓/Sd0d%10 gE_S3/ {ே/l,K/+6.l3.ߣ#'}uC0qH0/QA1A/ګ0ޤfLί ǯ101S.)0_կl3.l3-q0W0Y00L0.l0/=Tu/(,,`MG!". Nunimh /FJ/!0T/xsl^nƯ᯷xj\&.ᯈc_3l3,9n-_/%U+/F;Éoc%mN/?tlM09HмI*X/﩯#0.6>/yl4/ /u}SlylQA/l3/h$.FJ瓰֌L"~}^* .ׅMG|[Q4dFV|Y/(n^˯|YyZ_/PM[QR:.Ȕ9 %- *o̼/Z[Jn0l/yى0T,//0=O0g 0fAp聰K' ֧p-()08u Dit6&x/a/&NG/0 I*=/3H/~R/0a0L0ˮTҵ/د~&XݔL.a)0ׅhX{$\0{^l&Ȱvrtwn/H/(+:b!&Aΰzw yb0A0C U. \I0(D0QAD/ Ʈ֌L6|Y/]- 0&Ka0|¯zeP/~k +8.w|@c&N/?!//Di*ݤh|b# F.elm=0x,'.h¯/0ZL/y0G5*o/Fʯ5.נ//FbTX{i ꕰ 0'2S/t|=-?. wn]I*9n-+C8u.j;AMӰ2/F4Uh)7:܂ބ/EԮNb5X/~&y3Sg00q80mN҂0Y&/ 0E(0a/ /{0M>/:`e0D/݋x:I06qaX0?0%0)/[0E;90 Ϧt?!.001(@/_՚60^Y:/ߣr .^0l-k0V/cȄ0:{^쯾e)K/7ܛÉ0"~/ߣb#L/*կ^0*,XRcѰ9舘gEIc 0BEQ=wA-0Kut 0=0ܮ6܂0;ˑߣ#0K/֌LE/A/ł1SA0ze.n0ԅ.i0 5﩮;0ïհr}0N/*!c׮:gI=/8.ˑi@0y50n/T. F򼥮QA1S0MK05/j\/>T="JzS֓0#1N>(4V/PJ,r ηE,֯n-rO@T-mo߯/<[ٯ9n-j;/qUݰ{V$r>.:g.]I)rY x'Gc/s/tMh8/")/@S.9nˑ/Ax0,,/C0#1zaE::gI>T0!x J#/!p\55/'XM/ 00:0/8ũ=0$/:gI.o.2"0sʮ݋-0%0^/H_/1SE/_(@e0ra6>8u-/,*,.XO@g.z5=Zv:bp?/&dI*/Z<)(/kǰ2ᯪk T39n.1.JU00X.4/sc^5tuu48.S3.*O!mS/a)U0E8/!:0׾70Aߣ#pN<.}-0X0nj/ F.ߦ0,S3̰Eے09nq/@V֧oc)(yNcP="~{ 'ۯZH0.Dp/\a- (~/-ӌ//ڰX>(j0:b0]<[0Zz/Վ5/_/D̃=870.l?!.0 I*/(vpyl40 /8u.a/ 0/j/,,l8u/.l0ˑ(-Gf {^l/:-ȯl. N?48uD$\/MK/WZm- /M/vm֓o.a0Qm8C 0QA%\9n/+d/~z0Xa0Xo3ȯ$\'0nj/rJ0r///Z,&0FA/火݋{^/K0/ڮ.Xު Ixs/_ /00^/O!aiZz]o&/ ,I˂/ 70\/ze/,,6/zeP/{^". ~&6J#YE+DV>087/cW~RX.%/k0='?º0¯Ɨ/c/^/z70 ^008s0=06;ۮh0..8u .//d/ %R0'G l-kG0X݋o&[l.MSI*/=20wA-/u֮߮4ʯ*00$\y50eZ/}0龯|B0֓00JUܰU/y5^wR F/)/bt|Y.5 +̃"'/CsR)ު/{Њ/.l? ,L9(.L/8/e.b/V$~T0:gI-\J/ {`/gE./Ee/!/}/k/rV/_1/0P/:`l3,/fS2//^:t/q8/"^5w/폰t)0/kk ̃=/vvL <Ļ/(v.ުnꮦQ90x:I >/ 0կ[QL//l3ˊ!_,/5:`/!bl3'.*0]u*í*uͯy5/ %-5?ͯ ,O!0d(+Y}/l/l/(v// Y06/!0-+ԅ0.vQA0P00T/#/tzQ/="/o//00D0vH0:`e\|0fLN/2\.ބ /R.QA.Q/u龮As0x/uu %/;1SjD0Q6>/r30S0z0.lO@/\C?0+FW/a^?!/v 0E/8Af/S3̯Y É/ު.ˑVΑ/s0"~/v/T-ů&N/!ԮK*0- 0"0~RJ.;00p60 ./۴0%03/֧.e!ǰC//D-Z/.8/6 N650~& /oł/40T/q/)08uY00k/3+0i0WVS/)D0?/V>"1/.MK.A/gN&0x%0d.R!:⯷x4,K/KU/Uǵ//گ7>/&0֧,+ai/ۯ`0$\/ g//#/njeZQAfLNA0h0:`.?/Я//=6/ZL0/-Α/Z0Gf../A//a/PY0*/뷯o/K/֧l.1Pr0t''}/1/U/`M/É/Uw/+0uu0a/g{0n. /!.x:0H0V l3,E/_0<0׾7#4D0T,a2000ު.e!G7ׇ/`ͯVvn0 /rj0C׍0/.u&/0-:/É/0_t/ߣ#/h®O Aܮq/ /a^/-H'G/ׇm/TA[Q//L/40rMˊnNv .(0|'/8u/n/./FJ*^/(]Sł/߯$p//KUD ./J#ٯl/o&/ު/:>T+0X0DpXE0U/,05nj/ /d/0Y& F.5fS20^ܯq/($0&(/xTX0.l/0%./*EԮ-xq/nh9n.E/xsg0?0Z/CN.: /M˯c0.,,'/ҵ.km/L/ӯ)D,Zc׮_fS4-.Tze/;˟/_-!.l0/./"0>(ۯ֧\qz~&/"':gI-/JկM8e!GH\/+/'K4:gI- (zeЮZ/0ïxs/QA0{ÉE./^/+/hB/l30 0.6k0}/bzeP(į8s/0/Ư.uu+@0 07/*/%/00S3.B0$V/0 T0 D/ڻ0g~9/0/0Zk=""0\C?/C/>/6Zh.fS/#.?M"0/.AV ' 00/jB6+q/r/5E/(// 4Rh/XOB~/'/ ʯ20د/ˮ._0:g-0$90"0 "/u+.خ-ȮH0+߬qU].`]0RM09C.U030.p\A00W/6>.C /)?^/֧񊺯ɍկ/}b0./X0f'01S.2#0C;Y&0?f#)/̼ //Z/f.?!.̃=J/1.E8/f?QA2<.B 0^/K5n߯8u/'m.Ny!⮇.S3̯/5yl/)0ZH// b/6>.~&s3 0π /y 0(/j/ڻ2,/V/)DfJ;^5EےŮA\|00 I„fLN=D$*/A0"~/$y.jܯ_3/=".Z/v//x>0+/=_ /'3y5/]P0C ř}0\rB>/\sOR/ 2,,U0r/)̯/rѯg~/j/3H/x 5xŭ=/k4/#a$0 /5(/ik0p\[q/>T3 蜯π /vr/=mN.0 /(/;0&0<Ļ.~.ze.2r0av/D.^/Eے0/e0 (//q.s/|r/(@./D-fSO@vBV)45r0VWﰻ\/=;0b0QAf0WI}Ě[q/vQ5{/4/R:0.C 7p=Ɠ0L)On@R/$\0$\߬vQJ/+Q9/fS2\p\V0EwB.q.e/*?U 0/گyl .8/*.,J#//ZP.^0&l0->T0ipq0/ҵ8uo07j}0kt/0p#r0{/,,/~/sO+//1lj0Cw<0{i0/s̃=/C 0Zȯ00Α/{XE?/^+/E8.&䯶 /^У/\ 0ǭU -۴8u:/rEtqѥ0KWZ-+//l3.C n1:G6-.Z/0F/ #0M.t0a^/aUg90k';2/H.0/ϧ/Et/̼.~I0?h¯\nj-7`0\sR:0$ .~TT},D/ai/g/u/؈0e0ʯ0o*//*.I*=֓/jܯ0ʯ-.2//Aa.M5?^h®^QA//Z./֧.T010%R:0/QA.--H0q<0;˟/..l3e0:@J.!磯E0܎"̃ai/&/qNꯞ,v0j"0&NG.R:]06/r(" ЯE.0)䈯. 0T,h/5/~Үvw//Ic0X/l/j/FU. 0l/_~R/yl/aL8)0/3/ 0}:h50f/FìMR%|Y/=m-p60w./}Ka80,8.B~ 7=!l3ҵ/sʯx8n3/70l(0mE0/Z08u?뷯8/ٙ.6.s09.//s랯/T,h0^/qUݯ3H-k/d4ة%j+NK0) 0="//@?0p#/P/K^5/-#/6 0o&0AĢ Y&O@X/A Fֆk 6>Y&K/*t// Hܮ~د_gb]0o&]!~UY?0̯qȯE/h/./..zt/ׇ0*0u01h030w:s1/H0 000o}/tkۯ|s 5E5V~v .D1*'1J- 1,c002"70\C/gEj0Ȱ/0p0x.%U+njطӯĥ0;*گ3헰40K,ܯnj.vXϯ '龬Z/(M0 nj 02q_0} ewa/oc%1 T+0+o6yl4^{/Яp#ӁC;LX.N.wA-j\/$\0 ^/qW.pg00\|0Qg//0g.$h0/(="//Z.N.0?!./+^50Fr0p0/継/͡/l?o|0z.".6>VM\J#Sl0M /`Ҝ438.ׅ/ԯ?2,xs?a/e03~:g+90/eO/'}o⨯/#T0m-0"0b /Tm0'C0C'c- .E..$\a,/Ib 0W"Ю$0F|٭.0 /30qU]3SK' V_/|ɦ֯55c&S0*,y9p 3sR)+x 6:0 -JUx3ު..iۯ,0%/_/WZ3PߪU0ˆ`دrd0#Ѥ,0gUt/79~*0_ʎ/iS0P)0N/'&NG-H %үҵH0{. /{ .\G/0D ήc_"݋/VR0 F4կ8/B/ZF\.8s/">/+6.s}/Vůew/L z!b-Q/֌Ll>ү1-Y0r.D/8u/ .V$8!DZ{0~z0<~A0ުّ/ĥ.Dp/_7/Qo/ȯ^nFxzN@rQ &߯V.r0=U/?!./.m/|)0'/K.f{;/S/ì .`ͮůfS2.ّ /^/< ԕ/[+o6)1//̃/" I/rN]0A[Qįm0/?MR:0-hG°{/g~/F7\|IA02F10 /AF/=/x /A3H&/׾7/ͅVW/ YР/ %/Y&.0nǯai.B0V EV0QA.հ?!/x/z.0I*/O~0/Af.`MfS20֌L0rd0.l/ Iҵb/600+@m-3/?) fC2mέzǯ, ` gk 0X.ѯFJ#0H/V/}1Pc/~.(ᯄ,Ѵ/ .Ozǯa˸/\q04/l~므Q~z0+C/{.7C.:/.'ط0~&/|'/\C?/=;\Jp/`/.5/}0 20Cw.Ku0="0'Zz c0O0(D0p\/AR:0vxO/50p.(g//'|ɦ.33e!G0pfL.^I*/{i+D /!5/w/!d/*.+o60G0QA/߬q.>/~&Z070߯'}/̃.qUݮ1Ӯٰ"%U[Qq.D0p\/K6/}߭n.C/-AF0I300)/7'}/"~/+0?// 0`i:G֧{V;҃G8#_3ϧ`/ %R'l3,Dyl.-:q0}Uv0s/]t_1]?/ze.l {`/QA-r09nm.5ER:.t/00__"~..C/m/ˑ/P)05rѯjR:0cW<. bw4"*/ʿ/a,-;˟-H<08u/PG.1Px4&2[/_1/ĥ5\/-/`ͭ(.?1<20Cү.4agtx.H1!nj.8..k/lm=0P/!10v.0s/nj/>(/Cҵ.X3/g {//ڭKx.A0r307/1.)('̃=/7GZ#E/ɯA*0.R:0(- %LN`0jܯ/Ѥ,l0vD0A[0n}-070N70E08u.c0rѯ {^l/.a/ 0b#0Xv/t|/87/Z %/\/'ު݋aޮ֓a/t.s/_/ v n?0F-O.9n'Gcڄ/ـ/L/&O/ڮ8.x*/!-X0دZ.9n-0y0$#@V/.a-an0I00//,&0I*=a80fLN/طS0ZMK (/+0b/30//0}/C>m0b${0"0c@//گ.-/(]/彮/$\.Af8i/J/n6y/.00c՚طӯwӯ/0&R:0.ҵ).//%UC5/_/..-&NǮu&/>(/6/6J 8u/'Gc/j.F{0̃=E h¯[z5=0[-qʯQ /~&0/j/L8sNyglv ewQ3/p/F_@ 9n.ai./,t뭢ʫH1!;ʯ?Eے8u/)HܯG8a/w.yl.3uCq/?.}ޯCw<0 80a.π 0/Iʖˑ/ު/ߣ/,-Hvv.E(0Aj/\ 09?FJ(I;ބ %үٰo˰p\A09nM0O$ 0nj. {`/Ԯ!/֌/龯݋.0 b/Qk00~z/F-T0fLίV$00//:Q03Р|/!`M/oQ9(.wn/'0|'/jX0r/p0A/3 /.j+0Cw<ݯ(ݯ.Q:>0Пcׯ戏lQAL`M/6 6//%U.<.0i0ބD#h/=/F1/<0XEm0*0qUݯhwU0F0P0.. /戏0{笯Q.F/H1/c0"a/q/rHïp0g{a-1)0Ԭ p\AXO/x ak.0Q10! /.:'-(,^e.lO b௯߯L/wS3̮l31P/".G-qʿ@ª/ '*03H9>B\0y/Y?0݋/ 4<0@.(@"~/h9kx// )//zeЮ/.fL/*U0fS2A)0V 0.n/h/S/bT0p//.(/ϧ`c?/8uM˯80.&NGtS{^ˑ0M0Ѯ0l3-VFJ/G8/%U/BEQJUL0P//:gɭ/L/mή{;mN.B0V0 0/[Q|/ԅ02,/S/ FB~/ ,/Z.ߣ.!H\.7A/دB~ ^nF?!.!0/~TT0/ڬX/A/_,6J t֌L/nx0JNH ]<ۯxs:`.Q/0tt/gEj/ F0Z/cW2,!Z/J#ٮ0݋ߣ./%므ѯ~ү/m8_l3- >$ 0QA/̃.\s/0yE0R/Ɨm0Ia0./Ʈ?./eb/-/oc%/N/!0Q9 40ρFmN/.ŧ o/6 %/Af|s' /֌L0C/^ͯ/v+07j//(/"/J:`e/LgC]/3.ͩ/:A2[/}/@#V̱/0-0|#0/"k /0̃./{0s1Ue0 %[0I0'-f0U]0#r0q,///,z40&0.331_0S.mo࿮8uSlĒX. p//H0a/QA//?M/J0|¯߮2[J#Yߣ#/5E.wu<ίS_+1Pr⇰sZH1/@S.߯v W.ު0z./Ɨm0.OU0'XL0.3.Y0p0$p/֌L/m/:04/6 p/8u-g0N/T/-:/c.m/mΪ+.bg+-/x@s#hBfL/֌-// .&d084]u*z.-/S/Uy0"c//bԯ .0ى07/w./ۣ/H_\͈/x {`=Wn(H5 ^!0ܮLN`.FD0.h/u//+/-A/﩮%U/8.3}/sưE0q,fS .C8/AP/30].-gqll>VMP=.k /zeЯ(͵-:.м-'/jsJ0b0D0p/mN-\Ϝf.x0!/W"֯șOJ//YR0X0*.>Oi0/BEѯ/L/0y$ 0_0t t I50\|/}0#/̱o/޾/S}0nj/ {`/qU]. 2j4_ـ/OR|Yk 558u]<[/e!G0/D0Z/'/Sl>G"8i^0M//P/f!/X"0`/0/%0$0Pv+o/R:.\/;҃ G7_.'/*ݤ/.ʰ椰0GI:/(%wد*qF2[M./;r(0e/RBO'/gy2p;/Y0/0D'/ ǮT./O/^5/+/G-.:6//NygS/c/:`.QEׯF14;U݋-1 & . ?!/RW@5G.z0b0>"R/ha/kG0CX0\/+//l3-+0!bv 06095ޯ>0  0e!GS/]/W)0//Di/ۮEے-%y F/sJ/.d(/WƯ5P0G8a5V.9n-/QX//a/H\ip~&{n/3e/^X/|105/S/)ު..^//ϧ`/`]00'02u0/A.8P.U02RJ0z0+/yqH֌L/BEѯP 0fS.Sl/d0O♋"3060z/B0*oʧ/zKODHv/k /H0߯i0Hïw:{/c?//IL/[|Ư-0t'0/dѯ!.".}0ծɮ?!1="-Z 8u,p0\㘯"#.J4/iI/U[/?گE8/NMB009n.[%[s̃=Dp//^nF/hB//v®:`0v¯4d/Ѥ,0l3{/oJN> On/e.H.JE0..A  ,A|//Q0ـ\3.{01y/\S3̮0a,/8u.:$4/dǯk#1 _Ɨm0e0,C0/o0l?/߬/>4}ѯYTѬ/p/M/-9# .֌L-//+/-'//ٰ/G.l3/T,h/0|:/b͐0vPQAU80"N.5/O0 ,6.{^a r/ ..OR/Lg/'HO/$@K&0$/odU'0'РY诬=4dXn/$}-Jկ8ut20//߯ Iԯ0/]<[ /0B0X0ߣ.'}s㯾e/x.E7MRG,i0Jo/[0/Zl3/x/)/;j I/0'J0 (0&x0/Y_/ sm6,;0֧,IZP05/ܮ* 0 D/zeЮ_/X`L!.5 .y -{;.l5E.֧./xz .l/uïG!0 ƯήD0}0/nj (/.[Q/JU./w0+/Αy0*/z.0-0 .'T#40x//y5Ƌ/UE..X/D,>B5/b5-/_gb++//@/AfEï9?/yy3寔 0-Jn0J0ٰ/f0_1ۭ;0<Eԯn/;Я _uV/u0/-0.zePΑ {/5M˯A.(0 +0E.0*f"/0E/݋,̃=/ /!`08(r/j;/0_8u?ͯ-***=K0EK/nj/ /Cnjb/m/0e/J/(/..b]JX/S%U-֯j/$\n/-/3 fLN./*ޯL //!DpX9n---e/e!G0/:0rAL50'00[0cW..!0CI0M09xsfS.)(l3,T,h F|Wb0&NG<,hR0e1ӮeZU1)0uïz0%u&l+'G/خ%a/q/p\JA.m'Gĥ50p. D/l30\گY/0>s0A/,,9n-W©/&/X/"Mqc. f0/CT,/3C0n5E./_@060{-H/3H/6"'3헯+ Iu0(0}h/c/0/e/(06J֌LR:0݋]/?ͮ\q/Ѥ,QA錯^5w80jܯ4 0<) ]Ic /P/ -ˑ,n k 0 .~&0y5/XSjߓ-}801S``/M˯zW//r!0ZH+՚uu.H1!hB!0>(0ߣ./ai.buA0߬﩯֧,/<v/0.few 0D=0h)0 խbT/^560Et0 7/F/T*ﮈ6/ F.\J/00Tc/=T/L0d/vD0̼ /k0/ߣ.DB/(@rdtv)!1.> ĮO/戏090s?^ծ+D+ܯ5/0G01Y./GY0+be/^0/T,/.-/0=0wn F/Kl3'/G8/좚/ Ue0?0U#0֧/ (!g/`R:.#80j{rYQE/2.v 0?/hB/H 0Z¯ŧ.g*DT,/;˟^d0< P/g0_쯋=Я=]1/Sc߯-ӌg:(y(/0 0Ax. /FU/̼ ¯/zU7.0{0N/b-0g/Rډ/U.@0/Qu*ݤ:t|D(05-񋦯.ǭ/x//vB0ۮ(<._/n`/^/UMK/%d /֌L/Ax֓0- ƯylBs͵(<)7 ׯ7 /H/080qN/©հc. wJ0,0g/a{0/TJ0*ve@.0/>sM/Z / /8EԮo/T./0sR\J`#B~ /QA/"00/X/G/X.bUv/(v,h/v/i@/笯30wp\.a}/\J#/Oa'.9@/F4OKUD/l3gvEЪ$Is`M|@@J/{^r300/<ٙ.MuD+t0{N01I>.C0/-/8/)/ބ.p#/>0!b-S(/M 0ݹ/0^/.l/ 70c-U"0(ˑ9nv F1l(-(5xE/^:}^t.&NG/7/:`e5ET,.p.r`ˑR08u.ބ.N6Qk1o.W+cY0.-T,hG/p\AS/` ή.ۯ֌.}.Tr.Zz/P믡0g0A0O/Ic!00l3ߣ//uC1a04Z/k /j0{/|}'GQA.CX0̃=//.۰@J/4/ ./8B¯ZV0(0T0[Q0V$0B~ 0z.x-ׅh՚8./Zj\0Suܯ*0wK'0 / /05.9n-1S0x(@/_3ί %R/N=&0H1/0ɿ\0(xb/30.m/3.7w[0K.l.a,~c.0''G.E/"/0%U|B/j//n.mNewg0q/I0 0 e0 F@ʯ 8-(0?0&//!bh\ɯ0//PYބr3///4.&NG'/qe0.-FmHph0rwנ.xs./FJPY0?8u. "0eZ!/(v~gBE/8u֧@01Sz/?ͯt 0̼/S/)j/m/ 0\Z/@J]-btN%0.XO/9n.V/|b0GOKkxP /qNy< 2d X2"70y/nXEF/lw=ů/!Ld.lf/ˑ.@/rO!05/گYد\\0w/4>N//[0A/Dg!/O`0'.Z.dǯ5H2) o/d/x/JU-i 60/A0(D.7C&0J.H*/H/#1#X/n0Z.g0қp0j[T/i02/X 1?.J\J/"/-//m3H0QQV"~.,S//)毒?/',o 0%c0ߣ#."ͯk -llx0Ny篦B0.{PV/ .nK//Zˊ!4泯Pݽ1/-/:$\/a,/i{0R:0Y0 00@Ig~I/\J_/'0GJ/Ѥ,ޡKr.+5Uy±/0]/h/0-=0'..^nF/طS/X.7/X@'1CFʯ/F{0?.lm=0j\/[A.lvKZ讬:.U."~.˰3H\CB0/s1/yZJ#Y/Α/r/1P/7C&ުD۴0~Rp02r3/M/;03.570_ـ01hT,h.+>0{/j'/|ׯ@i@X/'/ȸ.`/&E/ /ބ/p.<+/`0k/p\A&NG/:gI,N녯!j/H*r C.`0A/x60[QQu0;xc,//.fLN/Ny#/aޯzeP20nj// {&0@ʮ|ɦ/=".C/ZFs0mN.:9 R:/%U+k;R0¯q@ʮmb7ïLM7/g/@ʮȝ/ ,/zeЮl3,XO/101w#0oP 0uq-Dit/#X/(֌L8uL %0<Ļ5Ů+.(@EFʮ|¯t|Z.t?QA/udWb06 c-tڮe/#6t(-ȭ//火#1k 07`0Sf0oS00$#@/ /=",u:f0U0ٙ6/lfY0=/h/S.\ .^5w}{/'790wR0TyVRX&/!b/PY/-ӌ/S}I)/0\,gïN/ @VT/ ,6y/U0-/ Zlҷ1fc//(143{yc5/ZyFOD/.V`H Qy/|0$/A{0)r0 j1Ml3.ak/ 0Q.>/ᄰqߣ. .'3LFnU~.-F/ZL//<0/PG Ztl/e/m,eH;/ 0-|/Gf/R[08/G8t.ծ ٰ /ܟ0RٝήA/KC 3))0sMհ8/ .|#K/Fq/g//.g0J 0!/|'.C%06Ic/ '[QvG/*._ į6/./FS산bTiNygS}/C B/mS /a7 . %R. 4..5 /zkۯ#+//U5Uy֧. Pٯ:g//ٙ-Ƣ̺40[K9Ϛ_g⯁J4B!PE0VLU.lˊ?^4/0kx7C&0n0 03V>/̃ݟs/ z&NGnr򂯬:s"/G/<0 %ү)K>/ CX0c/8i006/(.8/ Yx0D0O䡮FJ.C0(hٙ!/40/-\|/ ,6/;˟./'0w0+eZ.-X0F@ʮ.!ͱ/gJ#Y/&NG/j#, p^f0~:400S0"06/2/_@ -5@S1.C xJ#/y5/!bmkt//A0/(/fLN._3/wn 6>-R:0.\/8Et0 0/y50_ I08 I!/$\.h¯eZ/\soc:`4,0lN/4B0?ޯˊ!D,.9n-qx.V0]AF//^u//0 P//+0񫯝 0T,h/@60S/09S0q5EOa/A@C .Q?8L-*vE 0r,*0y='G/|B/5)Cy.Z0 ,.1.~&֧wѮtk*v]0 b/Kl/'n_/X.'0+iN0I00(8}+%6@׾"~.0s10' /6*?ͯQAT/r/``0hGB0:/*0⨯/.0(@0T:9 /xtV(0rY 0]vH0 80(@ߣ#/K^00E0QA./v0 /r3.oZiطS4G8r'&050 \I/#)j ?o/Z0&/?.1/XS3.}ʐfbN0֌.nj.lM/ѫ/X:0E/A7qů~!Ss$ 10"{/#-.uC//ʘ5E/NqK/Ş0").b\^02b]/ʆ.vH.#/C/ݮ'Gc/l3#//)d5/!u5?v.*|ׯ 060/8u.V/_ ,6!.E/G0ˑ0ʹ<0/I*=G-f//1#01P>Ԯ/J$E0E.#T)/A/0]0T7 n-MP8/Tf/&u)S0c,0h HC.c.X b/kq.8uЯDit/6W/ٰo/U0Qu. 010K0 /ۯYV 0oeZXW ԕ/ʯ笯:g/[ѯD,wyO}V/T0 TXT;/s /f/c_"b$}U^S4.Վ.b/K[/#D./s=jjqH)r/X0^nj/ު.p\A0g04d PY I//5.+.& 0)9./)_.6, 00ׅ %R// 0aO/E8 ǃ)0 Ʈ(\s-D /pţ{Tg&2'!b.dM FC>ml/#04,0k];˟Ŵ.r/0KR/i0N녮F1<)0".(v-!0ɯ-$Ù/e!Gbԯ!ͱON.0uM0h/ .k0/ˊ0MG/Z:/f/YM/d/P+50qH/q'"0j/wD3T") `y, 0iۯ//Ѥ.0P0/! R1c/]%)1S/ׯS3L/ǭ..v0I, 00T !0ĥ5G:/&dFA)05Ů`ͯl ...]/N0 .N/pE/ke',F.CqT,-LxnuD"/\J./>Ģ/-.o&./~/XE5O0L/`M0UK.G-q0wޯQu0ٙŞ/C/$*$K0 T,h.mV0(@z.}/x.,b<2e00W/n>ӯt0#vB*/J\ e/FJ.rѯ*U€D,:/tk/ ,6yl4+/0!cW.&K@Jc1)03SCI%U/!j/ӯ,\Jmc?/3Ȯ(v.DB0CsJZz/د873 /.b^.,,I30\J#/ߣ#+Q5gEF-0HC0)0E_FJ/1eZk _5OV֓q8=").A/-ȮXv ֓0f0<Ļ/_0LN/!b6/Ŵ/=&0\L/.a0a./ -:/~. 6/\Z<./[XT<)/0xs/nj/?M0.0#/|ɦ\J#Mc/^Te9n-QA/wL.\.-8u.'/UB~29n-H/~&É/ˑ߯ - 0.C,./#/d(+0yZbԯ O/łˊKٙ6>//-:0sO0h"S3.7̃=&NG/O'0vH0/a8.xZL/ٙ/n-Yh0L0oߣr3/ˊ!/Q/ qU]0+0QA/l/įt:^*/^4!/ߣ/i[f:gI0aޯ+yl4ĥT,.M/%UC>mhB/F0ׯ/k .?cW.=%/Cw<0ӯ/.afS20ԭo 01S/o&/^//^/ %/QE/݋O/oc%*./="G80=W/nj/T,.Q/!b/̘/h/м.#8H_100[Q/0!b(.K0r0+@0?//$\\ X-ȮQr3`Ҝ/euu֧70xsS3L9n-l?DV/R: }6/طӯî*0-/yl..V a鯾+Ao՚/A]0#T;0 I//<0e9.0fLίo01l0̯ĥ50"050Pv/8K0j0t|Şѯ .S3̯--0J#YZE;90łEH1/c׭ .U"VLw0_,nxs.Qk%ܯ4/)/c5ŭ(0ìp#0"0zů3/㯂|'Y1|j; 4 02/w#y*2W/@#gE.. DJ...Z/ /.. 26J_Gf.mϻ0_-0[/J.DB0@/ Y0į>(.vvL0QR0n0r/2.Zz7 W0mD0׾/"0"06;m.ؐ//p/<2\s]- 0X/tӯ{Њ/Te7055Jίϰ0Y&/(70!b04/wޯ7V/s":`e/T/C0t /Kc-0f/55J#YF0܂/'/Ɂ0(/a.5 ,.^0&0偯fS2/;˟/r&0V^0y3/I0yIưCql3-g~%%;G0$\%LoĢ9n-DqkS/a40鬲S/) 0/|.W[ˊ.Ģ0Q.WbGf@0[]|//̘j/.U/Yy/9nnsO/^.{^쭻%,\O/i7{^l/, /j0h0a.B/p/K'.p0$Z0U"/J#ٮzEӖd[;C ބ-q(ixC4/$KeD'A/~R/,/V.ޥ//M0?/5/.Sd"'r05ϮG60//@f/+՞/1Soa^ ƭx^wSF0Jq.W0r//Zx/ڮ^tP/ï) /~/6J 05!|/*?.KTX0<0%a 0՚PU/0$d(5 0n+ׅhη0b#/=0ȝ/05/5P!Ǜ/|)/`XWb6J =]//՛0/m5ˑH/}Sh2"jvW©/MM0 0/T௷wf'])0Mp_3#h#%Яb|ƪ/ŭlo|׃t0p@0')/Vqz0]<ۭT. /4Gb (0S0]\ /{qZ///~]Quk<GJ;b=t亮B.ůZ0E/ 'X0Bٹ/0AL.$#@xj\S篔$Qv uM0%/B<0QDM˯0G/E3i0{b=w/8$0MHi/RI0 /Q1%/./hB,-!.C /ˑ_@/FJ-/L0k+/B/a_Z0N 00/4d0`Ҝίv¯ՎC/0ɯ/ Ю<+Fm_u./=/MQ$0{`D0ji/\ɯ^8 0>/@/$.U /֌/~./S$0i/ 0A%0O0BE.uN 0U/i@:/zeЭ./njS/Eےh0>VM0$90v/L/ߪ/Mw/}[8:g+{LՎ/?R:_.A0.0W/ /ׯρԅI"0-^Y0!`/3/x/z/ 6J/".V3k0v0W.S0w#i/J#Y/^nFs/D+I*<2и:`../tkiK1l05+0./F0 / 0Zz../9n-/ˆ/e.a.L/6 0mN.l".Z/%k0:gI/.l :`-?/E/XT,h/I0/Z0Q.eZE_SlE0/\J#/ 1 %z:0笯죆0]/ɍU>s3r >.Q50\suVq/l3A0fS.50.S0%UjN/R:5 !-/or0}5w7U}vD- uï֌._]<[/).r/2;b/b(<+Ư.-\1}"0R [/[0N0%B00(0S0b0!`/:06 //F0-0(yN0/Ưp70a/g/:`eJ\(/+[8/T,h0c/i7.k#0./Im/v.4/*/>s/8u/e/m!/vî Y0.HïI*=|0䀰~&,! 05E.2]JVͯ]40+/fS./ U/q-=;YDi՚/C>Oe/A0R!0j/h/D/$/1Ӯ\J#/A-ȭZ/\C?X_S3̮.ٯJ/xٙ.0J0w0V/E/;˟/%ܯZ/ȯwn/Z̯/&!;҃`0m//5/ZHC/q.5/E0/.Hl00/g/Af06-/!ͱ/S0'0f0y.5.=\Z̭K.\/:gɬ"'*-H/ .l-/$\/qUݯh.0`/(yN/S/1207C/0ބ.w3.E/﩯rC r/|ɦ.WX;vH/p0r.y0/6q/9n!LC@EϚ*=˯CImK$0?!.0)OMsJL08uK+/v/b${0.ٯ<{ //a0}ޯj.?E/.ބ)rQ10$#/]ϧ`!.ݟ(]T,h.L}Y诼0K/006خa/(I;0/ t/+o6/E./6 0/t0\d 0O&0*U0P/-.I//v+^.'<ᮝAF/:,]ϕ07L/륖/@o/;'Feԯak.t/P.YX]u!b,0PfA)0κ*5?GfqV 0z/8򗯺1#LC2"77 W]>0)0e/`<%]0*U-//00/D ί :`e1//m8/\Z///AԐ/{ .ZG_0Vb03z$0?/tί!ஷ/0/L02Ԯ=/|/CW".6-/WZYM-jt0c<*o$+IxB(ꀯ&2-90Uvfqo˃Cw.0/ٙ/!/>'&ɘKV5-U뷬\C` /ݹ/ /i0l/noү~TT/! /D/hd0/])/H/y}/ xlЯ.#0/͡.Mq/;/eUB#0F0ưc/cpkk Nq,6ί1l˯ӂ.^d`#/w^.[0v~0ad.OH]/0z. P/$N//9f/1𮬘/#6-H.*u.C/s/៯Rt0_q 0C=9.8ul'0̃=.5E/g0O.y5E/n//MK0ªA/p.ߣ#.BhLLfJvA}0U0g[^FҺ0JI.B⮰hK7.em 0Tͭ0gt0*20+׬0_1O0$*Ic ?.{0<)40_01^ݠ0ml0!X0 Fˑ/kzN0=0ZK&0>B(/gï 0ʯf$ 00ѢT4꛰C/fc/r/.@= m/-:X0nj.t/8uxsł.Cvw/֊t0/|Y/gEꭇm\qz0S}0K&=\,׎0&0hL0 b0x,0Ѯ>0ku02[0l?]Zʎ/%0 Fق0$%/)0r(00B0&>*=˯Ch))0.c./"e080bg0|K^/a|0Cί0)0!N/}//{9n-,3/ 00N[H0I/6>amNhh 5(//Fm/cWdǯiۯ&8V.4d/ﭖ]F0ew0/:/%U/5:. W0 eQZ0~.0/0P/ӯʿ@,e0&K P/P /_j. o.l.b3e.:+05/⿯̼ '缮)x$$/yl=S/?K3T/ǎk.T.9/?/0ыo/ɉ0k !~=.T/ Injvr/M0a,ى/,HR0iJ1/Q-!/? 0,,-0v.B0{/دE 0X/F0C/~k0b/sS0Zկ3r/ c/0\|/fr0z0y3.2/+_1.ޭ/J4*/z*j/R!5<8dX>w/q, ǯL 0?.,.h`# 72,{^--=KUįD/c.gt0G-/"~,hR}""ͯt x' /^/c?0Z.xs. 0eY/An_!10u(=Wg9㱯//준0"G/^/)0J\(0~*///^nƮ).kM0O䡮 Iu/L/DpX//._.5wYSWP\/b]ʯr/p/Za/抯[HK0/!-X0 0z.0/n1(/κ4/ƘY0X0k/ł,4t|L066J 0篌I0Z/uu0^/rKu.F/a0G-^>30/oĥ5qH0>(._.֌.f.xl3Oz~]1)|W0//J#YP/w&0u\/X.{0/0R:- E (v.S03>/{-`/*Cb͈zO~TԯfLN.UFB=;BE &03S.Fr/kG/̃=/^5Ůl30`l0\6Tw{0:Z>O/$0+q00.&:gɫt°S3̭U5^=0^0{^l.(yί1Ӯ}.:gɯj/p6[/w/ad9.SO@[dD0J#ٯ )D/L 0m ū/50N0Rְmm)D/dl.>L3T"03H/(@/0ﯞlM40t{///Et/vC//05/.Mi[Z.t|./eDz.V-6>Y&0!.S/ʊ0j+o/ܯEԮ-&x0خ0c,/QZz//ry5]0Wb).^ PY ѰSK0" .qU]0gA/J06v0w/ٯ/.m`0h{/B/)K$ɯu&*.@/-ȭ㖏4/!0/O ;Dn'\..P/F{/.?/s10n.@$ʯORN/T,wnĩ/(X01Pr.0y,F10 ȋ0k/Hh\/ϯtnj .V6%/O.hB/ȝ,.5[N/Te.8_O/X/"񯎁6>.EےR8XA//FʭO/hF#/F/o*֯w0.0#(L//΀Q7 W&'м]-/}-q-/QT]/u:A/g׮ &/0sbXeY/ 0W/q8/TE/Y//02y s.賖o/ˊ.Ŧ/X/0%A0_/y/WY0\v/̘//;Z/eZπ/Ni/f/8L/@}I!1 /|&/zϯ8h/] \0.K xw\,f*}./e/LN`Zac¯-Nt/P=dðz /x/{^lî/|YY&0W/ p07sȕ/}"i/L}0t 000>'0l00>/b030R0t/9n.B//U.@?]/߯M.f050rz{. )cW,/̂Q4.-uV*0Ux,V8/ dϯ D:@/g /?^@-JծEK 0/_/1U0 )0d+?/$p/0c/OP0w/\e04/Р/Wb'/إ/0/=.՚.JFmϻ/;R:3k.0>V/]s/+7AG/to/e0$u0 - D0/ 0/"{ЊdgEnj =To0' F\} 0n0I0/C>/0c0/͈/|X%0͹V/aU/8˯У{,ɯN/mқ09/Xۭ;0d&0 0~6/:\|L0Za/90ή.O0/0;҃0\J"m0^u/|9%[x0/X2l.\/.lkz./}[0zeP/&Kxs.O!/#.sR/oc%E.Ll(qNy֯9/N.K%10+.,hR0QUy/)\SK /]vB010C,,/a~//1-/ /$0fU 0偯jD_=.VWF0N./\C?0՚/0W..mή{/v/k .뉰 DV 0oc%/Fm$0//8>04d/80/87/"/hB05E.QoO/, O/ //e.Ej ?м|)M0'.8.XWwnL /-dįVP /=c?/6>-5/@֯S!`.0[ԯv/9n-c_.hw.uu8Ŵr/\@?t./(6/0Ax/t:!/ᗳ/.<.t2/0q0&W//hwU0p 0ѬH*/0[>j0C/TʯQ@(0G0g /D/f/rPQ$Q{5G/c_"¯00/=/U/*0^)0O0r0ì.&NG/h.#/6뮮h.IZPPv3Sd/:gɭR0c//2?9760QAO V /:9/6W///^whw/Pq/9[uXX#/e/ɖcWTyl4-L/~/zeP>Vͯb/- 0W+ 0[qκ01Ցذ/2RJ6J /~0 2/0i˯5. ?j"0}[8ߣ#o&;/֯<0נkٓ)#1WYG0(/lo /j/k tQ/a+߯ Kwa,/Y0w/hDuV#/Y=0طӯ@J۵0)rj/ 0)K0r/>/,02F//@W00F0r/E0A//e0~&/30= 0 ݮA{N0/n/03Ů5k0ʐ+S3.Sjï}/y./O_η/i{mp/*^G0LMX0[ GQPmB{'/|24:/=".ʷ/G://G./_ d`ҜTܤ/ S&/kq%0 @/09t/|cMEDv//vwL/3]:0%R0gH0R/J,/Ґ0 3Яu/d(+/*0/K`B ;2*/t.֯"/>..|s 0PwP=d/H6/8/>Ifk8V0Sbs/q*pS0Wb//e.cT/m$ -/+;/U^SH&\86LY;k/ Xd0F../ 0+ï(QA2/C VE/&7{ 0}0/`50f0$.v.y>k/.{'u/U3%@c.G8/ R1 /.Hhx?bԯy3e쯿lv~Y0;/J㯚)䈯.c3H/>B/LN`0G8mЧ/ /tmhqǭ2<) xˑZHsϯ/įB/ܯI/͡/r.B0j0{ _ 0t|// 쯁끰Ēk Gf;҃Ax/y/2MG|H0'/CI/ή/ڻ06;N0f_0t/#80~k/̠8sEے=/yG0c?/.kxg/|/Y0PF 0l3+W/l=20Xā00c0'0k0A/y^H"~Yh/_.f/8/0v0/瓮DK/򼥮د;'Q뮯a.;˟.8u-h_$oݔ=-ss~qcǘbY>iDpخD+ܮ_04,/.݋6;ZΑïP S00W/gEj6. 0/A߯_-|/%$,0zeP`90oK&uu. /a8ɢ/׃W/ /|.ܭD+/40f/p/I00^ 0M0 v/EB"'//5xb/Q W"-e/a2C8/8<¯*//_l66$ #jIg@o/@"0*o-k | /f//.f/4O/!b.S/Ӯ]._}/ -x7{/4DA10!`000/%MR֌L.ǯ#/B/.a/ʆ./Z`/,40 sw-5宬Ӻ/k//`/.Y/ٕ//Mp&W0X/rZ/b0$ .h .ln)0 ӭIuV) E0P1D.?d){aA%i~r/ݩ/ɖmNl*/S;0@//)K0d.rZeX5+q/}0F0) 0- ΍/±%0{a 03h$ì}/.(00jDzn 0(+0a8'.`]0m/̼ m-/e:`,S˯ބ-|/A/Q0{;/.//(/M魰b#n1:0߯K'p\A[Qocӯxa魽/).Di="./`MK/I*/!/]8-n/+)/.-/VZ舘宇/Q905006>.彮/X/B0/%k'S/!]t:<2[/u/(A/tZz-%U+. 򼥯D-?:T0\ p0 ٯxRr`/6,//ܮ3T"ު0^>30Ӯ!1/ //ƽ/C':4H0_/b${ ŧ mD0c>/賖/!hp8fS2i/Ia?/i@^0˰ORWN/"'"-i@ޯLN6=8u+^5wqz.a/2/ط//R!0 j۫.zg(o .5/y>/tK/C.'s/n/笯@$0+6g p3=7C/Lu&wM:gɯ0֯(@$/jqHODA/=ׯ-TBO+6/u0 /Ѥ,/򼥮0| 0:0ș/I/gEL0`/錯fU wn2Fm$//"`/ϧ`/>'0C0ԍ/A01į,,9/߬_#e0K"ȥ//]/X /L/ͳP0:./LU0/ޮ@bDjuD/"X/C $0e0:̃= (.{ЯR\00Mߵ/ku °~/ L:[nL /C /Q+0/i0 0LW0 I/Fm${^li?VIP0'20$s00n//},0Z0?/<0`/կ/ZH:DׅPFүL-/k=*04 /@S/}0}ɮc_w@}#Umk-///ku 0Iͯ/Ud6zYoGW0//0joӯ"8[0D=I0+x0/1Ō08u.jo/S=瑯Z/N/uO0"`60¯">0]ݠOd3//U EB|=.-0D'/E0a/.-^r/PpW00|it. ]s/ /&讑>M-Fq/0hu}/S/S.ƙaߛS0.dj/2"0̱/^/0Z/Z?tdnXxw8 {`.$#@Xip. \/Z̮A /Rյ/B/F.b-Ɨ._h)jvat/;2D 0z.u>s0+r/ٲ.6/M/.8㱯/G9:236-e.}I,00Y/.賖-/ /P.$u0B~ܤ(/7j}/hQ//p3/ /tQ{i/A $f/qqe0K0-":9/|B1/#1ٙE/-Ps.l9&0U0][/;/ae60\0'Gc.hC/ّ3ۯ70NGD/2RJ0gM50Ĝ.Ԯx;*v{-̯x 0 #6%/wߒj/ȝVxDwd-fb/I/08p=0ъ/,-=)˯%0;گNɯo/[5//bԮ/z'G-У/uh/{0;҃/pȑ0^~&/.8uH_\ :mh.̴00o(,a,0 I/MG|/KUDt)bѫ/m[,0=/l㯘0/Ӟ4ԍ0}90Ku/ qU.;҃-0k ->"|'!n_.κ//€/0//.ʏ-0WZZ/cȄ#%h$0Zz.95ޯO鯰od(+ ")b#"/~$Al3+9hw/0HC/fLN/'(/x /eŤ-/@0,g~@3/t uCrOs/!> .p.G/D'P>ޯKX.X؃دG9Y&/ngX /ʐ0l3,mE]>/&f.D;*ZsO~-T0 Y/ͮ:./ }l_IY/즂x0 /6<i/-Ҡ.SJ0η0}//a,y/A0`j&0M!zůa-2/W/u.%40Y&/L0kݯW//+0$Rg0jT/9p{`įcq00p0Gf/!b.9.z10ܭ/PIe//.'H/H$XJX/Ȓ/iZ/q//Q//@S1W"Pu/_hN/C>40`@@Xu? נ/賖l A/(.9S9n-hʯV.EԮq?0AS¯R1tG[=+R00O/j\.ӯqN %/;0X☟ 0HBr >/^xѯ,0򼥯APV00ꧦ/V40B.",A0>)n⑻zo.ai.!ʆ/~0F/LU YՑX.0TT/RׯG.y 0)/渢.~/eZT('w/;8".o//%//h0ٮS0|/3K0+? #/- y>J0'/60S%Z.R:JkTS>.Z/*-u/J /nb9L0`/c/o,M&0w9Z /K:6`9.M/jC"0-0X/鬲/N7.YX/Ǹ/vBѯ1/9/wq@/T ^/G8m0h.Ҧ1S.z.//ߣ/0y3e0N?3ȭl/é90м,gE꭯10N/5/W/6 F/Ϊ/뷮0zePu}0fSv.{ ImQNygI*=/E}"i(/נ./H0$\0-j*7ǯUC-X+.q_=.SS/Z/Ɨmg_$*$/!6c_"0".+.(I;p֧/?0/=^0C0̯.(/(.gE/"'\qHh0N/0VdZ/6y1/CXYZ//^/^wp/] 0/7 /1|0k;R0drc-3.2.2/source/doc/octave/lowpassfir.m0000644000076400001450000000226011320622700017137 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: f = lowpassfir(n,fc) ## ## Compute an unwindowed lowpass FIR filter ## ## n = filter len ## fc = normalized cutoff frequency function f = lowpassfir(n,fc) ho = fix(n/2); c = pi * fc; if (ho == n/2) f = sin(c * ((1:ho) - 0.5)) ./ (pi * ((1:ho) - 0.5)); f = [ f(ho:-1:1) f]; else f = sin(c * (1:ho)) ./ (pi * (1:ho)); f = [ f(ho:-1:1) fc f ]; endif endfunctiondrc-3.2.2/source/doc/octave/safetics.m0000644000076400001450000000242213162664216016565 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: safetics(axis,tics,[labels]) ## ## Set tics and labels accordingly. ## ## axis = axis to be sets ## tics = tics to put on the axis ## labels = optional labels to put on the axis ## ## See also tics() ## function safetics(ax,tc,lb) if (nargin < 3) # Imposta le etichette # tics(ax,tc,sprintf("%g|",tc)) # tics(ax,tc,eval([ "[" sprintf("\"%g\";",tc) "]" ],"")') ptics(ax,tc,num2str(tc,"%g\n")); else # Imposta le etichette ptics(ax,tc,lb); endif endfunctiondrc-3.2.2/source/doc/octave/blrebase.m0000644000076400001450000000310311320622700016522 0ustar denisitadm## Copyright (C) 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## This function is part of DRC - Digital room correction ## usage: rs = blrebase(x, y, xi, flen, fcut, att) ## ## Rebase y=f(x) sampled on the uniform sampling vector x ## on the uniform sampling vector xi with a filter ## flen taps long, fcut normalized cutoff frequency ## and att dB of stopband attenuation function rs = blrebase(x, y, xi, flen, fcut, att) # Computes the resampling factor rf = length(xi) / length(x); # Check if it is a downsampling or an upsampling if rf < 1.0 rs = fftconv(y, lowpassfir(flen,rf * fcut)' .* chebwin(flen,att)); else rs = fftconv(y, lowpassfir(flen,fcut)' .* chebwin(flen,att)); endif # Computes the filter delay fd = (flen + 1) / 2; # Recompute the base xs = linspace(x(1) - fd,x(length(x)) + fd, length(rs)); # Interpolates in the new base rs = blinterpolate(xs,rs,xi); endfunctiondrc-3.2.2/source/doc/octave/styledmesh.m0000644000076400001450000000465111320622700017135 0ustar denisitadm## Copyright (C) 1996, 1997 John W. Eaton ## ## This file is part of Octave. ## ## Octave 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, or (at your option) ## any later version. ## ## Octave 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 Octave; see the file COPYING. If not, write to the Free ## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ## 02110-1301, USA. ## -*- texinfo -*- ## function styledmesh (x, y, z, style) ## function styledmesh (z, style) ## ## Plot a mesh given the optional vectors x, y and a matrix z corresponding ## to the x and y coordinates of the mesh. The string variable style ## defines the gnuplot style to use. ## Modified by Denis Sbragion from mesh to add a generic style parameter function styledmesh (x, y, z, pstyle) if (nargin == 2) z = x'; pstyle = y; if (ismatrix (z)) fname = tmpnam(); eval([ "save -text " fname " z"]); __gnuplot_raw__([ "splot \"" fname "\" matrix " pstyle ";\n" ]); else error ("styledmesh: argument must be a matrix"); endif elseif (nargin == 4) if (isvector (x) && isvector (y) && ismatrix (z)) xlen = length (x); ylen = length (y); if (xlen == columns (z) && ylen == rows (z)) y = y(:)'; len = xlen * ylen; cb = zeros(3, ylen); k = 1; [ bf, fname, msg ] = mkstemp([ tmpnam() "-styledmeshplot-XXXXXX" ],true); for i = 1:ylen:len cb(1,1:ylen) = x(k) * ones(1,ylen); cb(2,1:ylen) = y; cb(3,1:ylen) = z(:,k)'; fprintf(bf,"%e %e %e\n",cb); fprintf(bf,"\n"); k++; endfor fclose(bf); __gnuplot_raw__([ "splot \"" fname "\"" pstyle ";\n" ]); else msg = "styledmesh: rows (z) must be the same as length (y) and"; msg = sprintf ("%s\ncolumns (z) must be the same as length (x)", msg); error (msg); endif else error ("styledmesh: x and y must be vectors and z must be a matrix"); endif else usage ("styledmesh (z)"); endif endfunction drc-3.2.2/source/doc/spline/0000755000076400001450000000000013165107356014617 5ustar denisitadmdrc-3.2.2/source/doc/spline/spline-cmp1.eps0000644000076400001450000007633111115436646017472 0ustar denisitadm%!PS-Adobe-2.0 EPSF-2.0 %%Title: spline2.eps %%Creator: gnuplot 4.2 patchlevel 2 %%CreationDate: Fri Aug 22 13:19:21 2008 %%DocumentFonts: (atend) %%BoundingBox: 50 50 410 302 %%EndComments %%BeginProlog /gnudict 256 dict def gnudict begin % % The following 6 true/false flags may be edited by hand if required % The unit line width may also be changed % /Color true def /Blacktext false def /Solid true def /Dashlength 1 def /Landscape false def /Level1 false def /Rounded false def /TransparentPatterns false def /gnulinewidth 5.000 def /userlinewidth gnulinewidth def % /vshift -46 def /dl1 { 10.0 Dashlength mul mul Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if } def /dl2 { 10.0 Dashlength mul mul Rounded { currentlinewidth 0.75 mul add } if } def /hpt_ 31.5 def /vpt_ 31.5 def /hpt hpt_ def /vpt vpt_ def Level1 {} { /SDict 10 dict def systemdict /pdfmark known not { userdict /pdfmark systemdict /cleartomark get put } if SDict begin [ /Title (spline2.eps) /Subject (gnuplot plot) /Creator (gnuplot 4.2 patchlevel 2 ) /Author (Denis Sbragion) % /Producer (gnuplot) % /Keywords () /CreationDate (Fri Aug 22 13:19:21 2008) /DOCINFO pdfmark end } ifelse % % Gnuplot Prolog Version 4.2 (August 2006) % /M {moveto} bind def /L {lineto} bind def /R {rmoveto} bind def /V {rlineto} bind def /N {newpath moveto} bind def /Z {closepath} bind def /C {setrgbcolor} bind def /f {rlineto fill} bind def /vpt2 vpt 2 mul def /hpt2 hpt 2 mul def /Lshow {currentpoint stroke M 0 vshift R Blacktext {gsave 0 setgray show grestore} {show} ifelse} def /Rshow {currentpoint stroke M dup stringwidth pop neg vshift R Blacktext {gsave 0 setgray show grestore} {show} ifelse} def /Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R Blacktext {gsave 0 setgray show grestore} {show} ifelse} def /UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def /DL {Color {setrgbcolor Solid {pop []} if 0 setdash} {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def /BL {stroke userlinewidth 2 mul setlinewidth Rounded {1 setlinejoin 1 setlinecap} if} def /AL {stroke userlinewidth 2 div setlinewidth Rounded {1 setlinejoin 1 setlinecap} if} def /UL {dup gnulinewidth mul /userlinewidth exch def dup 1 lt {pop 1} if 10 mul /udl exch def} def /PL {stroke userlinewidth setlinewidth Rounded {1 setlinejoin 1 setlinecap} if} def % Default Line colors /LCw {1 1 1} def /LCb {0 0 0} def /LCa {0 0 0} def /LC0 {1 0 0} def /LC1 {0 1 0} def /LC2 {0 0 1} def /LC3 {1 0 1} def /LC4 {0 1 1} def /LC5 {1 1 0} def /LC6 {0 0 0} def /LC7 {1 0.3 0} def /LC8 {0.5 0.5 0.5} def % Default Line Types /LTw {PL [] 1 setgray} def /LTb {BL [] LCb DL} def /LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def /LT0 {PL [] LC0 DL} def /LT1 {PL [4 dl1 2 dl2] LC1 DL} def /LT2 {PL [2 dl1 3 dl2] LC2 DL} def /LT3 {PL [1 dl1 1.5 dl2] LC3 DL} def /LT4 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def /LT5 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC5 DL} def /LT6 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC6 DL} def /LT7 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC7 DL} def /LT8 {PL [2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 4 dl2] LC8 DL} def /Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def /Dia {stroke [] 0 setdash 2 copy vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V closepath stroke Pnt} def /Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V currentpoint stroke M hpt neg vpt neg R hpt2 0 V stroke } def /Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V closepath stroke Pnt} def /Crs {stroke [] 0 setdash exch hpt sub exch vpt add M hpt2 vpt2 neg V currentpoint stroke M hpt2 neg 0 R hpt2 vpt2 V stroke} def /TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V closepath stroke Pnt} def /Star {2 copy Pls Crs} def /BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V closepath fill} def /TriUF {stroke [] 0 setdash vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V closepath fill} def /TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V closepath stroke Pnt} def /TriDF {stroke [] 0 setdash vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V closepath fill} def /DiaF {stroke [] 0 setdash vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V closepath fill} def /Pent {stroke [] 0 setdash 2 copy gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat closepath stroke grestore Pnt} def /PentF {stroke [] 0 setdash gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat closepath fill grestore} def /Circle {stroke [] 0 setdash 2 copy hpt 0 360 arc stroke Pnt} def /CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def /C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def /C1 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 90 arc closepath fill vpt 0 360 arc closepath} bind def /C2 {BL [] 0 setdash 2 copy moveto 2 copy vpt 90 180 arc closepath fill vpt 0 360 arc closepath} bind def /C3 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 180 arc closepath fill vpt 0 360 arc closepath} bind def /C4 {BL [] 0 setdash 2 copy moveto 2 copy vpt 180 270 arc closepath fill vpt 0 360 arc closepath} bind def /C5 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 90 arc 2 copy moveto 2 copy vpt 180 270 arc closepath fill vpt 0 360 arc} bind def /C6 {BL [] 0 setdash 2 copy moveto 2 copy vpt 90 270 arc closepath fill vpt 0 360 arc closepath} bind def /C7 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 270 arc closepath fill vpt 0 360 arc closepath} bind def /C8 {BL [] 0 setdash 2 copy moveto 2 copy vpt 270 360 arc closepath fill vpt 0 360 arc closepath} bind def /C9 {BL [] 0 setdash 2 copy moveto 2 copy vpt 270 450 arc closepath fill vpt 0 360 arc closepath} bind def /C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill 2 copy moveto 2 copy vpt 90 180 arc closepath fill vpt 0 360 arc closepath} bind def /C11 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 180 arc closepath fill 2 copy moveto 2 copy vpt 270 360 arc closepath fill vpt 0 360 arc closepath} bind def /C12 {BL [] 0 setdash 2 copy moveto 2 copy vpt 180 360 arc closepath fill vpt 0 360 arc closepath} bind def /C13 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 90 arc closepath fill 2 copy moveto 2 copy vpt 180 360 arc closepath fill vpt 0 360 arc closepath} bind def /C14 {BL [] 0 setdash 2 copy moveto 2 copy vpt 90 360 arc closepath fill vpt 0 360 arc} bind def /C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill vpt 0 360 arc closepath} bind def /Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath} bind def /Square {dup Rec} bind def /Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def /S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def /S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def /S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def /S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def /S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def /S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def /S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def /S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill 2 copy vpt Square fill Bsquare} bind def /S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def /S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def /S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def /S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def /S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def /S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill 2 copy vpt Square fill Bsquare} bind def /S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def /S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def /D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def /D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def /D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def /D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def /D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def /D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def /D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def /D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def /D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def /D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def /D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def /D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def /D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def /D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def /D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def /D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def /DiaE {stroke [] 0 setdash vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V closepath stroke} def /BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V closepath stroke} def /TriUE {stroke [] 0 setdash vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V closepath stroke} def /TriDE {stroke [] 0 setdash vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V closepath stroke} def /PentE {stroke [] 0 setdash gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat closepath stroke grestore} def /CircE {stroke [] 0 setdash hpt 0 360 arc stroke} def /Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def /DiaW {stroke [] 0 setdash vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V Opaque stroke} def /BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V Opaque stroke} def /TriUW {stroke [] 0 setdash vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V Opaque stroke} def /TriDW {stroke [] 0 setdash vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V Opaque stroke} def /PentW {stroke [] 0 setdash gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat Opaque stroke grestore} def /CircW {stroke [] 0 setdash hpt 0 360 arc Opaque stroke} def /BoxFill {gsave Rec 1 setgray fill grestore} def /Density { /Fillden exch def currentrgbcolor /ColB exch def /ColG exch def /ColR exch def /ColR ColR Fillden mul Fillden sub 1 add def /ColG ColG Fillden mul Fillden sub 1 add def /ColB ColB Fillden mul Fillden sub 1 add def ColR ColG ColB setrgbcolor} def /BoxColFill {gsave Rec PolyFill} def /PolyFill {gsave Density fill grestore grestore} def /h {rlineto rlineto rlineto gsave fill grestore} bind def % % PostScript Level 1 Pattern Fill routine for rectangles % Usage: x y w h s a XX PatternFill % x,y = lower left corner of box to be filled % w,h = width and height of box % a = angle in degrees between lines and x-axis % XX = 0/1 for no/yes cross-hatch % /PatternFill {gsave /PFa [ 9 2 roll ] def PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec gsave 1 setgray fill grestore clip currentlinewidth 0.5 mul setlinewidth /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def 0 0 M PFa 5 get rotate PFs -2 div dup translate 0 1 PFs PFa 4 get div 1 add floor cvi {PFa 4 get mul 0 M 0 PFs V} for 0 PFa 6 get ne { 0 1 PFs PFa 4 get div 1 add floor cvi {PFa 4 get mul 0 2 1 roll M PFs 0 V} for } if stroke grestore} def % /languagelevel where {pop languagelevel} {1} ifelse 2 lt {/InterpretLevel1 true def} {/InterpretLevel1 Level1 def} ifelse % % PostScript level 2 pattern fill definitions % /Level2PatternFill { /Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8} bind def /KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} >> matrix makepattern /Pat1 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke 0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke} >> matrix makepattern /Pat2 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L 8 8 L 8 0 L 0 0 L fill} >> matrix makepattern /Pat3 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L 0 12 M 12 0 L stroke} >> matrix makepattern /Pat4 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L 0 -4 M 12 8 L stroke} >> matrix makepattern /Pat5 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L 0 12 M 8 -4 L 4 12 M 10 0 L stroke} >> matrix makepattern /Pat6 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L 0 -4 M 8 12 L 4 -4 M 10 8 L stroke} >> matrix makepattern /Pat7 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L 12 0 M -4 8 L 12 4 M 0 10 L stroke} >> matrix makepattern /Pat8 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L -4 0 M 12 8 L -4 4 M 8 10 L stroke} >> matrix makepattern /Pat9 exch def /Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def /Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def /Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def /Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def /Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def /Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def /Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def } def % % %End of PostScript Level 2 code % /PatternBgnd { TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse } def % % Substitute for Level 2 pattern fill codes with % grayscale if Level 2 support is not selected. % /Level1PatternFill { /Pattern1 {0.250 Density} bind def /Pattern2 {0.500 Density} bind def /Pattern3 {0.750 Density} bind def /Pattern4 {0.125 Density} bind def /Pattern5 {0.375 Density} bind def /Pattern6 {0.625 Density} bind def /Pattern7 {0.875 Density} bind def } def % % Now test for support of Level 2 code % Level1 {Level1PatternFill} {Level2PatternFill} ifelse % /Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall currentdict end definefont pop /MFshow { { dup 5 get 3 ge { 5 get 3 eq {gsave} {grestore} ifelse } {dup dup 0 get findfont exch 1 get scalefont setfont [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6 get exch 4 get {show} {stringwidth pop 0 R} ifelse }if dup 5 get 0 eq {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5 get 1 eq {dup 2 get exch dup 3 get exch 6 get stringwidth pop -2 div dup 0 R} {dup 6 get stringwidth pop -2 div 0 R 6 get show 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop pop aload pop M} ifelse }ifelse }ifelse } ifelse } forall} bind def /MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse } {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont 6 get stringwidth pop add} {pop} ifelse} ifelse} forall} bind def /MLshow { currentpoint stroke M 0 exch R Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def /MRshow { currentpoint stroke M exch dup MFwidth neg 3 -1 roll R Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def /MCshow { currentpoint stroke M exch dup MFwidth -2 div 3 -1 roll R Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def /XYsave { [( ) 1 2 true false 3 ()] } bind def /XYrestore { [( ) 1 2 true false 4 ()] } bind def end %%EndProlog gnudict begin gsave 50 50 translate 0.050 0.050 scale 0 setgray newpath (Helvetica) findfont 140 scalefont setfont gsave % colour palette begin /maxcolors 64 def /HSV2RGB { exch dup 0.0 eq {pop exch pop dup dup} % achromatic gray { /HSVs exch def /HSVv exch def 6.0 mul dup floor dup 3 1 roll sub /HSVf exch def /HSVi exch cvi def /HSVp HSVv 1.0 HSVs sub mul def /HSVq HSVv 1.0 HSVs HSVf mul sub mul def /HSVt HSVv 1.0 HSVs 1.0 HSVf sub mul sub mul def /HSVi HSVi 6 mod def 0 HSVi eq {HSVv HSVt HSVp} {1 HSVi eq {HSVq HSVv HSVp}{2 HSVi eq {HSVp HSVv HSVt} {3 HSVi eq {HSVp HSVq HSVv}{4 HSVi eq {HSVt HSVp HSVv} {HSVv HSVp HSVq} ifelse} ifelse} ifelse} ifelse} ifelse } ifelse} def /Constrain { dup 0 lt {0 exch pop}{dup 1 gt {1 exch pop} if} ifelse} def /YIQ2RGB { 3 copy -1.702 mul exch -1.105 mul add add Constrain 4 1 roll 3 copy -0.647 mul exch -0.272 mul add add Constrain 5 1 roll 0.621 mul exch -0.956 mul add add Constrain 3 1 roll } def /CMY2RGB { 1 exch sub exch 1 exch sub 3 2 roll 1 exch sub 3 1 roll exch } def /XYZ2RGB { 3 copy -0.9017 mul exch -0.1187 mul add exch 0.0585 mul exch add Constrain 4 1 roll 3 copy -0.0279 mul exch 1.999 mul add exch -0.9844 mul add Constrain 5 1 roll -0.2891 mul exch -0.5338 mul add exch 1.91 mul exch add Constrain 3 1 roll} def /SelectSpace {ColorSpace (HSV) eq {HSV2RGB}{ColorSpace (XYZ) eq { XYZ2RGB}{ColorSpace (CMY) eq {CMY2RGB}{ColorSpace (YIQ) eq {YIQ2RGB} if} ifelse} ifelse} ifelse} def /InterpolatedColor true def /grayindex {/gidx 0 def {GrayA gidx get grayv ge {exit} if /gidx gidx 1 add def} loop} def /dgdx {grayv GrayA gidx get sub GrayA gidx 1 sub get GrayA gidx get sub div} def /redvalue {RedA gidx get RedA gidx 1 sub get RedA gidx get sub dgdxval mul add} def /greenvalue {GreenA gidx get GreenA gidx 1 sub get GreenA gidx get sub dgdxval mul add} def /bluevalue {BlueA gidx get BlueA gidx 1 sub get BlueA gidx get sub dgdxval mul add} def /interpolate { grayindex grayv GrayA gidx get sub abs 1e-5 le {RedA gidx get GreenA gidx get BlueA gidx get} {/dgdxval dgdx def redvalue greenvalue bluevalue} ifelse} def /GrayA [0 .0159 .0317 .0476 .0635 .0794 .0952 .1111 .127 .1429 .1587 .1746 .1905 .2063 .2222 .2381 .254 .2698 .2857 .3016 .3175 .3333 .3492 .3651 .381 .3968 .4127 .4286 .4444 .4603 .4762 .4921 .5079 .5238 .5397 .5556 .5714 .5873 .6032 .619 .6349 .6508 .6667 .6825 .6984 .7143 .7302 .746 .7619 .7778 .7937 .8095 .8254 .8413 .8571 .873 .8889 .9048 .9206 .9365 .9524 .9683 .9841 1 ] def /RedA [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .0238 .0873 .1508 .2143 .2778 .3413 .4048 .4683 .5317 .5952 .6587 .7222 .7857 .8492 .9127 .9762 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .9444 .881 .8175 .754 .6905 .627 .5635 .5 ] def /GreenA [0 0 0 0 0 0 0 0 .0079 .0714 .1349 .1984 .2619 .3254 .3889 .4524 .5159 .5794 .6429 .7063 .7698 .8333 .8968 .9603 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .9603 .8968 .8333 .7698 .7063 .6429 .5794 .5159 .4524 .3889 .3254 .2619 .1984 .1349 .0714 .0079 0 0 0 0 0 0 0 0 ] def /BlueA [.5 .5635 .627 .6905 .754 .8175 .881 .9444 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .9762 .9127 .8492 .7857 .7222 .6587 .5952 .5317 .4683 .4048 .3413 .2778 .2143 .1508 .0873 .0238 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] def /pm3dround {maxcolors 0 gt {dup 1 ge {pop 1} {maxcolors mul floor maxcolors 1 sub div} ifelse} if} def /pm3dGamma 1.0 1.5 div def /ColorSpace (RGB) def Color true and { % COLOUR vs. GRAY map InterpolatedColor { %% Interpolation vs. RGB-Formula /g {stroke pm3dround /grayv exch def interpolate SelectSpace setrgbcolor} bind def }{ /g {stroke pm3dround dup cF7 Constrain exch dup cF5 Constrain exch cF15 Constrain SelectSpace setrgbcolor} bind def } ifelse }{ /g {stroke pm3dround pm3dGamma exp setgray} bind def } ifelse 0.500 UL LTb 1.000 UL LTa 406 280 M 6556 0 V stroke 0.500 UL LTb 406 280 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 280 M [ [(Helvetica) 140.0 0.0 true true 0 (-7)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 790 M 6556 0 V stroke 0.500 UL LTb 406 790 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 790 M [ [(Helvetica) 140.0 0.0 true true 0 (-6)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 1300 M 6556 0 V stroke 0.500 UL LTb 406 1300 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 1300 M [ [(Helvetica) 140.0 0.0 true true 0 (-5)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 1811 M 6556 0 V stroke 0.500 UL LTb 406 1811 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 1811 M [ [(Helvetica) 140.0 0.0 true true 0 (-4)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 2321 M 6556 0 V stroke 0.500 UL LTb 406 2321 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 2321 M [ [(Helvetica) 140.0 0.0 true true 0 (-3)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 2831 M 6556 0 V stroke 0.500 UL LTb 406 2831 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 2831 M [ [(Helvetica) 140.0 0.0 true true 0 (-2)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 3341 M 6556 0 V stroke 0.500 UL LTb 406 3341 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 3341 M [ [(Helvetica) 140.0 0.0 true true 0 (-1)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 3852 M 6556 0 V stroke 0.500 UL LTb 406 3852 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 3852 M [ [(Helvetica) 140.0 0.0 true true 0 (0)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 4362 M 5233 0 V 1239 0 R 84 0 V stroke 0.500 UL LTb 406 4362 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 4362 M [ [(Helvetica) 140.0 0.0 true true 0 (1)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 4872 M 6556 0 V stroke 0.500 UL LTb 406 4872 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 4872 M [ [(Helvetica) 140.0 0.0 true true 0 (2)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 1062 280 M 0 4592 V stroke 0.500 UL LTb 1062 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 1062 140 M [ [(Helvetica) 140.0 0.0 true true 0 (60)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 2373 280 M 0 4592 V stroke 0.500 UL LTb 2373 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 2373 140 M [ [(Helvetica) 140.0 0.0 true true 0 (80)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 3684 280 M 0 4592 V stroke 0.500 UL LTb 3684 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 3684 140 M [ [(Helvetica) 140.0 0.0 true true 0 (100)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 4995 280 M 0 4592 V stroke 0.500 UL LTb 4995 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 4995 140 M [ [(Helvetica) 140.0 0.0 true true 0 (120)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 6306 280 M 0 3969 V 0 560 R 0 63 V stroke 0.500 UL LTb 6306 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 6306 140 M [ [(Helvetica) 140.0 0.0 true true 0 (140)] ] -46.7 MCshow 0.500 UL LTb 0.500 UL LTb 406 4872 N 406 280 L 6556 0 V 0 4592 V -6556 0 V Z stroke 1.000 UP 0.500 UL LTb 1.000 UP 0.500 UL LT0 0.00 0.00 1.00 C LTb 6311 4739 M [ [(Helvetica) 140.0 0.0 true true 0 (Points)] ] -46.7 MRshow LT0 0.00 0.00 1.00 C 1062 3852 Star 2373 3852 Star 3684 1300 Star 4995 3852 Star 6306 3852 Star 6594 4739 Star 0.500 UL LT1 0.00 0.50 0.00 C LTb 6311 4599 M [ [(Helvetica) 140.0 0.0 true true 0 (Lin)] ] -46.7 MRshow LT1 0.00 0.50 0.00 C 6395 4599 M 399 0 V 1062 3852 M 1311 0 V 3684 1300 L 4995 3852 L 1311 0 V stroke LT2 1.00 0.00 0.00 C LTb 6311 4459 M [ [(Helvetica) 140.0 0.0 true true 0 (B-Spline)] ] -46.7 MRshow LT2 1.00 0.00 0.00 C 6395 4459 M 399 0 V 1062 3852 M 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 -1 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 -1 V 11 0 V 10 0 V 11 0 V 10 0 V 11 -1 V 10 0 V 11 0 V 10 -1 V 11 0 V 10 -1 V 11 0 V 10 -1 V 11 0 V 10 -1 V 11 -1 V 10 0 V 11 -1 V 10 -1 V 11 -1 V 10 -1 V 11 0 V 11 -1 V 10 -1 V 11 -2 V 10 -1 V 11 -1 V 10 -1 V 11 -1 V 10 -2 V 11 -1 V 10 -2 V 11 -1 V 10 -2 V 11 -1 V 10 -2 V 11 -2 V 10 -2 V 11 -2 V 10 -2 V 11 -2 V 10 -2 V 11 -2 V 10 -3 V 11 -2 V 10 -3 V 11 -2 V 10 -3 V 11 -3 V 10 -2 V 11 -3 V 10 -3 V 11 -3 V 10 -4 V 11 -3 V 10 -3 V 11 -4 V 10 -3 V 11 -4 V 10 -4 V 11 -3 V 10 -4 V 11 -4 V 10 -5 V 11 -4 V 10 -4 V 11 -5 V 10 -4 V 11 -5 V 11 -5 V 10 -5 V 11 -5 V 10 -5 V 11 -5 V 10 -5 V 11 -6 V 10 -6 V 11 -5 V 10 -6 V 11 -6 V 10 -6 V 11 -7 V 10 -6 V 11 -6 V 10 -7 V 11 -7 V 2144 3612 L 11 -7 V 10 -7 V 11 -7 V 10 -8 V 11 -7 V 10 -8 V 11 -8 V 10 -8 V 11 -8 V 10 -8 V 11 -9 V 10 -9 V 11 -8 V 10 -9 V 11 -9 V 10 -10 V 11 -9 V 10 -9 V 11 -10 V 10 -10 V 11 -10 V 10 -10 V 11 -11 V 10 -10 V 11 -11 V 10 -11 V 11 -10 V 10 -12 V 11 -11 V 11 -11 V 10 -12 V 11 -11 V 10 -12 V 11 -12 V 10 -12 V 11 -12 V 10 -12 V 11 -13 V 10 -12 V 11 -13 V 10 -12 V 11 -13 V 10 -13 V 11 -12 V 10 -13 V 11 -13 V 10 -13 V 11 -14 V 10 -13 V 11 -13 V 10 -13 V 11 -14 V 10 -13 V 11 -14 V 10 -13 V 11 -14 V 10 -13 V 11 -14 V 10 -13 V 11 -14 V 10 -13 V 11 -14 V 10 -14 V 11 -13 V 10 -14 V 11 -14 V 10 -13 V 11 -14 V 10 -13 V 11 -14 V 10 -14 V 11 -13 V 10 -13 V 11 -14 V 10 -13 V 11 -14 V 11 -13 V 10 -13 V 11 -13 V 10 -13 V 11 -14 V 10 -13 V 11 -12 V 10 -13 V 11 -13 V 10 -13 V 11 -12 V 10 -13 V 11 -12 V 10 -12 V 11 -13 V 10 -12 V 11 -12 V 10 -11 V 11 -12 V 10 -12 V 11 -11 V 10 -12 V 11 -11 V 10 -11 V 11 -11 V 10 -10 V 11 -11 V 10 -11 V 3248 2386 L 10 -10 V 11 -10 V 10 -10 V 11 -9 V 10 -10 V 11 -9 V 10 -9 V 11 -9 V 10 -9 V 11 -8 V 10 -8 V 11 -8 V 10 -8 V 11 -8 V 10 -7 V 11 -7 V 10 -7 V 11 -7 V 11 -7 V 10 -6 V 11 -6 V 10 -6 V 11 -5 V 10 -6 V 11 -5 V 10 -4 V 11 -5 V 10 -4 V 11 -4 V 10 -4 V 11 -3 V 10 -3 V 11 -3 V 10 -2 V 11 -2 V 10 -2 V 11 -2 V 10 -1 V 11 -1 V 10 -1 V 11 0 V 10 0 V 11 0 V 10 1 V 11 1 V 10 1 V 11 2 V 10 2 V 11 2 V 10 2 V 11 3 V 10 3 V 11 3 V 10 4 V 11 4 V 10 4 V 11 5 V 10 4 V 11 5 V 10 6 V 11 5 V 10 6 V 11 6 V 10 6 V 11 7 V 11 7 V 10 7 V 11 7 V 10 7 V 11 8 V 10 8 V 11 8 V 10 8 V 11 8 V 10 9 V 11 9 V 10 9 V 11 9 V 10 10 V 11 9 V 10 10 V 11 10 V 10 10 V 11 10 V 10 11 V 11 11 V 10 10 V 11 11 V 10 11 V 11 11 V 10 12 V 11 11 V 10 12 V 11 12 V 10 11 V 11 12 V 10 12 V 11 13 V 10 12 V 11 12 V 10 13 V 11 12 V 10 13 V 11 13 V 4351 2644 L 11 12 V 10 13 V 11 14 V 10 13 V 11 13 V 10 13 V 11 13 V 11 14 V 10 13 V 11 14 V 10 13 V 11 13 V 10 14 V 11 14 V 10 13 V 11 14 V 10 13 V 11 14 V 10 14 V 11 13 V 10 14 V 11 14 V 10 13 V 11 14 V 10 13 V 11 14 V 10 13 V 11 14 V 10 13 V 11 14 V 10 13 V 11 14 V 10 13 V 11 13 V 10 13 V 11 14 V 10 13 V 11 13 V 10 13 V 11 12 V 10 13 V 11 13 V 10 12 V 11 13 V 10 12 V 11 13 V 10 12 V 11 12 V 10 12 V 11 12 V 10 12 V 11 11 V 10 12 V 11 11 V 11 11 V 10 12 V 11 10 V 10 11 V 11 11 V 10 10 V 11 11 V 10 10 V 11 10 V 10 10 V 11 10 V 10 9 V 11 9 V 10 10 V 11 9 V 10 9 V 11 8 V 10 9 V 11 9 V 10 8 V 11 8 V 10 8 V 11 8 V 10 8 V 11 7 V 10 8 V 11 7 V 10 7 V 11 7 V 10 7 V 11 7 V 10 7 V 11 6 V 10 6 V 11 7 V 10 6 V 11 6 V 10 6 V 11 5 V 10 6 V 11 6 V 10 5 V 11 5 V 10 5 V 11 5 V 10 5 V 11 5 V 11 5 V 10 4 V 11 5 V 5455 3735 L 11 4 V 10 5 V 11 4 V 10 4 V 11 3 V 10 4 V 11 4 V 10 3 V 11 4 V 10 3 V 11 3 V 10 4 V 11 3 V 10 3 V 11 3 V 10 2 V 11 3 V 10 3 V 11 2 V 10 3 V 11 2 V 10 3 V 11 2 V 10 2 V 11 2 V 10 2 V 11 2 V 10 2 V 11 2 V 10 2 V 11 1 V 10 2 V 11 1 V 10 2 V 11 1 V 10 2 V 11 1 V 10 1 V 11 1 V 10 1 V 11 2 V 10 1 V 11 1 V 11 0 V 10 1 V 11 1 V 10 1 V 11 1 V 10 0 V 11 1 V 10 1 V 11 0 V 10 1 V 11 0 V 10 1 V 11 0 V 10 1 V 11 0 V 10 0 V 11 1 V 10 0 V 11 0 V 10 0 V 11 0 V 10 1 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 1 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V stroke LT3 0.00 0.75 0.75 C LTb 6311 4319 M [ [(Helvetica) 140.0 0.0 true true 0 (PCHIP)] ] -46.7 MRshow LT3 0.00 0.75 0.75 C 6395 4319 M 399 0 V 1062 3852 M 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 2144 3852 L 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 -1 V 10 -2 V 11 -3 V 10 -3 V 11 -5 V 10 -5 V 11 -6 V 11 -7 V 10 -8 V 11 -9 V 10 -10 V 11 -10 V 10 -12 V 11 -12 V 10 -12 V 11 -14 V 10 -14 V 11 -15 V 10 -16 V 11 -16 V 10 -17 V 11 -18 V 10 -18 V 11 -19 V 10 -20 V 11 -20 V 10 -20 V 11 -22 V 10 -21 V 11 -23 V 10 -22 V 11 -24 V 10 -24 V 11 -24 V 10 -24 V 11 -25 V 10 -26 V 11 -26 V 10 -26 V 11 -27 V 10 -27 V 11 -27 V 10 -28 V 11 -28 V 10 -28 V 11 -28 V 10 -29 V 11 -29 V 10 -29 V 11 -30 V 10 -29 V 11 -30 V 10 -30 V 11 -30 V 11 -30 V 10 -31 V 11 -30 V 10 -31 V 11 -30 V 10 -31 V 11 -30 V 10 -31 V 11 -31 V 10 -30 V 11 -31 V 10 -31 V 11 -30 V 10 -31 V 11 -30 V 10 -30 V 11 -30 V 10 -30 V 11 -30 V 10 -30 V 11 -29 V 10 -30 V 11 -29 V 10 -28 V 11 -29 V 10 -28 V 11 -28 V 10 -28 V 3248 1960 L 10 -27 V 11 -27 V 10 -27 V 11 -26 V 10 -25 V 11 -25 V 10 -25 V 11 -24 V 10 -24 V 11 -24 V 10 -23 V 11 -22 V 10 -22 V 11 -21 V 10 -21 V 11 -20 V 10 -20 V 11 -19 V 11 -19 V 10 -17 V 11 -18 V 10 -16 V 11 -16 V 10 -15 V 11 -14 V 10 -14 V 11 -13 V 10 -12 V 11 -12 V 10 -11 V 11 -9 V 10 -9 V 11 -9 V 10 -7 V 11 -6 V 10 -6 V 11 -5 V 10 -4 V 11 -3 V 10 -1 V 11 -1 V 10 0 V 11 1 V 10 1 V 11 3 V 10 4 V 11 5 V 10 6 V 11 6 V 10 7 V 11 9 V 10 9 V 11 9 V 10 11 V 11 12 V 10 12 V 11 13 V 10 14 V 11 14 V 10 15 V 11 16 V 10 16 V 11 18 V 10 17 V 11 19 V 11 19 V 10 20 V 11 20 V 10 21 V 11 21 V 10 22 V 11 22 V 10 23 V 11 24 V 10 24 V 11 24 V 10 25 V 11 25 V 10 25 V 11 26 V 10 27 V 11 27 V 10 27 V 11 27 V 10 28 V 11 28 V 10 28 V 11 29 V 10 28 V 11 29 V 10 30 V 11 29 V 10 30 V 11 30 V 10 30 V 11 30 V 10 30 V 11 30 V 10 31 V 11 30 V 10 31 V 11 31 V 10 30 V 11 31 V 4351 2611 L 11 30 V 10 31 V 11 30 V 10 31 V 11 30 V 10 31 V 11 30 V 11 30 V 10 30 V 11 30 V 10 29 V 11 30 V 10 29 V 11 29 V 10 29 V 11 28 V 10 28 V 11 28 V 10 28 V 11 27 V 10 27 V 11 27 V 10 26 V 11 26 V 10 26 V 11 25 V 10 24 V 11 24 V 10 24 V 11 24 V 10 22 V 11 23 V 10 21 V 11 22 V 10 20 V 11 20 V 10 20 V 11 19 V 10 18 V 11 18 V 10 17 V 11 16 V 10 16 V 11 15 V 10 14 V 11 14 V 10 12 V 11 12 V 10 12 V 11 10 V 10 10 V 11 9 V 10 8 V 11 7 V 11 6 V 10 5 V 11 5 V 10 3 V 11 3 V 10 2 V 11 1 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 11 0 V 10 0 V 11 0 V 5455 3852 L 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V 11 0 V 10 0 V stroke LTb 406 4872 N 406 280 L 6556 0 V 0 4592 V -6556 0 V Z stroke 1.000 UP 0.500 UL LTb stroke grestore end showpage %%Trailer %%DocumentFonts: Helvetica drc-3.2.2/source/doc/spline/spline-cmp2.eps0000644000076400001450000007504211115436626017467 0ustar denisitadm%!PS-Adobe-2.0 EPSF-2.0 %%Title: spline.eps %%Creator: gnuplot 4.2 patchlevel 2 %%CreationDate: Fri Aug 22 13:14:13 2008 %%DocumentFonts: (atend) %%BoundingBox: 50 50 410 302 %%EndComments %%BeginProlog /gnudict 256 dict def gnudict begin % % The following 6 true/false flags may be edited by hand if required % The unit line width may also be changed % /Color true def /Blacktext false def /Solid true def /Dashlength 1 def /Landscape false def /Level1 false def /Rounded false def /TransparentPatterns false def /gnulinewidth 5.000 def /userlinewidth gnulinewidth def % /vshift -46 def /dl1 { 10.0 Dashlength mul mul Rounded { currentlinewidth 0.75 mul sub dup 0 le { pop 0.01 } if } if } def /dl2 { 10.0 Dashlength mul mul Rounded { currentlinewidth 0.75 mul add } if } def /hpt_ 31.5 def /vpt_ 31.5 def /hpt hpt_ def /vpt vpt_ def Level1 {} { /SDict 10 dict def systemdict /pdfmark known not { userdict /pdfmark systemdict /cleartomark get put } if SDict begin [ /Title (spline.eps) /Subject (gnuplot plot) /Creator (gnuplot 4.2 patchlevel 2 ) /Author (Denis Sbragion) % /Producer (gnuplot) % /Keywords () /CreationDate (Fri Aug 22 13:14:13 2008) /DOCINFO pdfmark end } ifelse % % Gnuplot Prolog Version 4.2 (August 2006) % /M {moveto} bind def /L {lineto} bind def /R {rmoveto} bind def /V {rlineto} bind def /N {newpath moveto} bind def /Z {closepath} bind def /C {setrgbcolor} bind def /f {rlineto fill} bind def /vpt2 vpt 2 mul def /hpt2 hpt 2 mul def /Lshow {currentpoint stroke M 0 vshift R Blacktext {gsave 0 setgray show grestore} {show} ifelse} def /Rshow {currentpoint stroke M dup stringwidth pop neg vshift R Blacktext {gsave 0 setgray show grestore} {show} ifelse} def /Cshow {currentpoint stroke M dup stringwidth pop -2 div vshift R Blacktext {gsave 0 setgray show grestore} {show} ifelse} def /UP {dup vpt_ mul /vpt exch def hpt_ mul /hpt exch def /hpt2 hpt 2 mul def /vpt2 vpt 2 mul def} def /DL {Color {setrgbcolor Solid {pop []} if 0 setdash} {pop pop pop 0 setgray Solid {pop []} if 0 setdash} ifelse} def /BL {stroke userlinewidth 2 mul setlinewidth Rounded {1 setlinejoin 1 setlinecap} if} def /AL {stroke userlinewidth 2 div setlinewidth Rounded {1 setlinejoin 1 setlinecap} if} def /UL {dup gnulinewidth mul /userlinewidth exch def dup 1 lt {pop 1} if 10 mul /udl exch def} def /PL {stroke userlinewidth setlinewidth Rounded {1 setlinejoin 1 setlinecap} if} def % Default Line colors /LCw {1 1 1} def /LCb {0 0 0} def /LCa {0 0 0} def /LC0 {1 0 0} def /LC1 {0 1 0} def /LC2 {0 0 1} def /LC3 {1 0 1} def /LC4 {0 1 1} def /LC5 {1 1 0} def /LC6 {0 0 0} def /LC7 {1 0.3 0} def /LC8 {0.5 0.5 0.5} def % Default Line Types /LTw {PL [] 1 setgray} def /LTb {BL [] LCb DL} def /LTa {AL [1 udl mul 2 udl mul] 0 setdash LCa setrgbcolor} def /LT0 {PL [] LC0 DL} def /LT1 {PL [4 dl1 2 dl2] LC1 DL} def /LT2 {PL [2 dl1 3 dl2] LC2 DL} def /LT3 {PL [1 dl1 1.5 dl2] LC3 DL} def /LT4 {PL [6 dl1 2 dl2 1 dl1 2 dl2] LC4 DL} def /LT5 {PL [3 dl1 3 dl2 1 dl1 3 dl2] LC5 DL} def /LT6 {PL [2 dl1 2 dl2 2 dl1 6 dl2] LC6 DL} def /LT7 {PL [1 dl1 2 dl2 6 dl1 2 dl2 1 dl1 2 dl2] LC7 DL} def /LT8 {PL [2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 2 dl2 2 dl1 4 dl2] LC8 DL} def /Pnt {stroke [] 0 setdash gsave 1 setlinecap M 0 0 V stroke grestore} def /Dia {stroke [] 0 setdash 2 copy vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V closepath stroke Pnt} def /Pls {stroke [] 0 setdash vpt sub M 0 vpt2 V currentpoint stroke M hpt neg vpt neg R hpt2 0 V stroke } def /Box {stroke [] 0 setdash 2 copy exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V closepath stroke Pnt} def /Crs {stroke [] 0 setdash exch hpt sub exch vpt add M hpt2 vpt2 neg V currentpoint stroke M hpt2 neg 0 R hpt2 vpt2 V stroke} def /TriU {stroke [] 0 setdash 2 copy vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V closepath stroke Pnt} def /Star {2 copy Pls Crs} def /BoxF {stroke [] 0 setdash exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V closepath fill} def /TriUF {stroke [] 0 setdash vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V closepath fill} def /TriD {stroke [] 0 setdash 2 copy vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V closepath stroke Pnt} def /TriDF {stroke [] 0 setdash vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V closepath fill} def /DiaF {stroke [] 0 setdash vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V closepath fill} def /Pent {stroke [] 0 setdash 2 copy gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat closepath stroke grestore Pnt} def /PentF {stroke [] 0 setdash gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat closepath fill grestore} def /Circle {stroke [] 0 setdash 2 copy hpt 0 360 arc stroke Pnt} def /CircleF {stroke [] 0 setdash hpt 0 360 arc fill} def /C0 {BL [] 0 setdash 2 copy moveto vpt 90 450 arc} bind def /C1 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 90 arc closepath fill vpt 0 360 arc closepath} bind def /C2 {BL [] 0 setdash 2 copy moveto 2 copy vpt 90 180 arc closepath fill vpt 0 360 arc closepath} bind def /C3 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 180 arc closepath fill vpt 0 360 arc closepath} bind def /C4 {BL [] 0 setdash 2 copy moveto 2 copy vpt 180 270 arc closepath fill vpt 0 360 arc closepath} bind def /C5 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 90 arc 2 copy moveto 2 copy vpt 180 270 arc closepath fill vpt 0 360 arc} bind def /C6 {BL [] 0 setdash 2 copy moveto 2 copy vpt 90 270 arc closepath fill vpt 0 360 arc closepath} bind def /C7 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 270 arc closepath fill vpt 0 360 arc closepath} bind def /C8 {BL [] 0 setdash 2 copy moveto 2 copy vpt 270 360 arc closepath fill vpt 0 360 arc closepath} bind def /C9 {BL [] 0 setdash 2 copy moveto 2 copy vpt 270 450 arc closepath fill vpt 0 360 arc closepath} bind def /C10 {BL [] 0 setdash 2 copy 2 copy moveto vpt 270 360 arc closepath fill 2 copy moveto 2 copy vpt 90 180 arc closepath fill vpt 0 360 arc closepath} bind def /C11 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 180 arc closepath fill 2 copy moveto 2 copy vpt 270 360 arc closepath fill vpt 0 360 arc closepath} bind def /C12 {BL [] 0 setdash 2 copy moveto 2 copy vpt 180 360 arc closepath fill vpt 0 360 arc closepath} bind def /C13 {BL [] 0 setdash 2 copy moveto 2 copy vpt 0 90 arc closepath fill 2 copy moveto 2 copy vpt 180 360 arc closepath fill vpt 0 360 arc closepath} bind def /C14 {BL [] 0 setdash 2 copy moveto 2 copy vpt 90 360 arc closepath fill vpt 0 360 arc} bind def /C15 {BL [] 0 setdash 2 copy vpt 0 360 arc closepath fill vpt 0 360 arc closepath} bind def /Rec {newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath} bind def /Square {dup Rec} bind def /Bsquare {vpt sub exch vpt sub exch vpt2 Square} bind def /S0 {BL [] 0 setdash 2 copy moveto 0 vpt rlineto BL Bsquare} bind def /S1 {BL [] 0 setdash 2 copy vpt Square fill Bsquare} bind def /S2 {BL [] 0 setdash 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def /S3 {BL [] 0 setdash 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def /S4 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def /S5 {BL [] 0 setdash 2 copy 2 copy vpt Square fill exch vpt sub exch vpt sub vpt Square fill Bsquare} bind def /S6 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill Bsquare} bind def /S7 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt vpt2 Rec fill 2 copy vpt Square fill Bsquare} bind def /S8 {BL [] 0 setdash 2 copy vpt sub vpt Square fill Bsquare} bind def /S9 {BL [] 0 setdash 2 copy vpt sub vpt vpt2 Rec fill Bsquare} bind def /S10 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def /S11 {BL [] 0 setdash 2 copy vpt sub vpt Square fill 2 copy exch vpt sub exch vpt2 vpt Rec fill Bsquare} bind def /S12 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill Bsquare} bind def /S13 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill 2 copy vpt Square fill Bsquare} bind def /S14 {BL [] 0 setdash 2 copy exch vpt sub exch vpt sub vpt2 vpt Rec fill 2 copy exch vpt sub exch vpt Square fill Bsquare} bind def /S15 {BL [] 0 setdash 2 copy Bsquare fill Bsquare} bind def /D0 {gsave translate 45 rotate 0 0 S0 stroke grestore} bind def /D1 {gsave translate 45 rotate 0 0 S1 stroke grestore} bind def /D2 {gsave translate 45 rotate 0 0 S2 stroke grestore} bind def /D3 {gsave translate 45 rotate 0 0 S3 stroke grestore} bind def /D4 {gsave translate 45 rotate 0 0 S4 stroke grestore} bind def /D5 {gsave translate 45 rotate 0 0 S5 stroke grestore} bind def /D6 {gsave translate 45 rotate 0 0 S6 stroke grestore} bind def /D7 {gsave translate 45 rotate 0 0 S7 stroke grestore} bind def /D8 {gsave translate 45 rotate 0 0 S8 stroke grestore} bind def /D9 {gsave translate 45 rotate 0 0 S9 stroke grestore} bind def /D10 {gsave translate 45 rotate 0 0 S10 stroke grestore} bind def /D11 {gsave translate 45 rotate 0 0 S11 stroke grestore} bind def /D12 {gsave translate 45 rotate 0 0 S12 stroke grestore} bind def /D13 {gsave translate 45 rotate 0 0 S13 stroke grestore} bind def /D14 {gsave translate 45 rotate 0 0 S14 stroke grestore} bind def /D15 {gsave translate 45 rotate 0 0 S15 stroke grestore} bind def /DiaE {stroke [] 0 setdash vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V closepath stroke} def /BoxE {stroke [] 0 setdash exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V closepath stroke} def /TriUE {stroke [] 0 setdash vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V closepath stroke} def /TriDE {stroke [] 0 setdash vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V closepath stroke} def /PentE {stroke [] 0 setdash gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat closepath stroke grestore} def /CircE {stroke [] 0 setdash hpt 0 360 arc stroke} def /Opaque {gsave closepath 1 setgray fill grestore 0 setgray closepath} def /DiaW {stroke [] 0 setdash vpt add M hpt neg vpt neg V hpt vpt neg V hpt vpt V hpt neg vpt V Opaque stroke} def /BoxW {stroke [] 0 setdash exch hpt sub exch vpt add M 0 vpt2 neg V hpt2 0 V 0 vpt2 V hpt2 neg 0 V Opaque stroke} def /TriUW {stroke [] 0 setdash vpt 1.12 mul add M hpt neg vpt -1.62 mul V hpt 2 mul 0 V hpt neg vpt 1.62 mul V Opaque stroke} def /TriDW {stroke [] 0 setdash vpt 1.12 mul sub M hpt neg vpt 1.62 mul V hpt 2 mul 0 V hpt neg vpt -1.62 mul V Opaque stroke} def /PentW {stroke [] 0 setdash gsave translate 0 hpt M 4 {72 rotate 0 hpt L} repeat Opaque stroke grestore} def /CircW {stroke [] 0 setdash hpt 0 360 arc Opaque stroke} def /BoxFill {gsave Rec 1 setgray fill grestore} def /Density { /Fillden exch def currentrgbcolor /ColB exch def /ColG exch def /ColR exch def /ColR ColR Fillden mul Fillden sub 1 add def /ColG ColG Fillden mul Fillden sub 1 add def /ColB ColB Fillden mul Fillden sub 1 add def ColR ColG ColB setrgbcolor} def /BoxColFill {gsave Rec PolyFill} def /PolyFill {gsave Density fill grestore grestore} def /h {rlineto rlineto rlineto gsave fill grestore} bind def % % PostScript Level 1 Pattern Fill routine for rectangles % Usage: x y w h s a XX PatternFill % x,y = lower left corner of box to be filled % w,h = width and height of box % a = angle in degrees between lines and x-axis % XX = 0/1 for no/yes cross-hatch % /PatternFill {gsave /PFa [ 9 2 roll ] def PFa 0 get PFa 2 get 2 div add PFa 1 get PFa 3 get 2 div add translate PFa 2 get -2 div PFa 3 get -2 div PFa 2 get PFa 3 get Rec gsave 1 setgray fill grestore clip currentlinewidth 0.5 mul setlinewidth /PFs PFa 2 get dup mul PFa 3 get dup mul add sqrt def 0 0 M PFa 5 get rotate PFs -2 div dup translate 0 1 PFs PFa 4 get div 1 add floor cvi {PFa 4 get mul 0 M 0 PFs V} for 0 PFa 6 get ne { 0 1 PFs PFa 4 get div 1 add floor cvi {PFa 4 get mul 0 2 1 roll M PFs 0 V} for } if stroke grestore} def % /languagelevel where {pop languagelevel} {1} ifelse 2 lt {/InterpretLevel1 true def} {/InterpretLevel1 Level1 def} ifelse % % PostScript level 2 pattern fill definitions % /Level2PatternFill { /Tile8x8 {/PaintType 2 /PatternType 1 /TilingType 1 /BBox [0 0 8 8] /XStep 8 /YStep 8} bind def /KeepColor {currentrgbcolor [/Pattern /DeviceRGB] setcolorspace} bind def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke} >> matrix makepattern /Pat1 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 0 M 8 8 L 0 8 M 8 0 L stroke 0 4 M 4 8 L 8 4 L 4 0 L 0 4 L stroke} >> matrix makepattern /Pat2 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 0 M 0 8 L 8 8 L 8 0 L 0 0 L fill} >> matrix makepattern /Pat3 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -4 8 M 8 -4 L 0 12 M 12 0 L stroke} >> matrix makepattern /Pat4 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -4 0 M 8 12 L 0 -4 M 12 8 L stroke} >> matrix makepattern /Pat5 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -2 8 M 4 -4 L 0 12 M 8 -4 L 4 12 M 10 0 L stroke} >> matrix makepattern /Pat6 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop -2 0 M 4 12 L 0 -4 M 8 12 L 4 -4 M 10 8 L stroke} >> matrix makepattern /Pat7 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 8 -2 M -4 4 L 12 0 M -4 8 L 12 4 M 0 10 L stroke} >> matrix makepattern /Pat8 exch def << Tile8x8 /PaintProc {0.5 setlinewidth pop 0 -2 M 12 4 L -4 0 M 12 8 L -4 4 M 8 10 L stroke} >> matrix makepattern /Pat9 exch def /Pattern1 {PatternBgnd KeepColor Pat1 setpattern} bind def /Pattern2 {PatternBgnd KeepColor Pat2 setpattern} bind def /Pattern3 {PatternBgnd KeepColor Pat3 setpattern} bind def /Pattern4 {PatternBgnd KeepColor Landscape {Pat5} {Pat4} ifelse setpattern} bind def /Pattern5 {PatternBgnd KeepColor Landscape {Pat4} {Pat5} ifelse setpattern} bind def /Pattern6 {PatternBgnd KeepColor Landscape {Pat9} {Pat6} ifelse setpattern} bind def /Pattern7 {PatternBgnd KeepColor Landscape {Pat8} {Pat7} ifelse setpattern} bind def } def % % %End of PostScript Level 2 code % /PatternBgnd { TransparentPatterns {} {gsave 1 setgray fill grestore} ifelse } def % % Substitute for Level 2 pattern fill codes with % grayscale if Level 2 support is not selected. % /Level1PatternFill { /Pattern1 {0.250 Density} bind def /Pattern2 {0.500 Density} bind def /Pattern3 {0.750 Density} bind def /Pattern4 {0.125 Density} bind def /Pattern5 {0.375 Density} bind def /Pattern6 {0.625 Density} bind def /Pattern7 {0.875 Density} bind def } def % % Now test for support of Level 2 code % Level1 {Level1PatternFill} {Level2PatternFill} ifelse % /Symbol-Oblique /Symbol findfont [1 0 .167 1 0 0] makefont dup length dict begin {1 index /FID eq {pop pop} {def} ifelse} forall currentdict end definefont pop /MFshow { { dup 5 get 3 ge { 5 get 3 eq {gsave} {grestore} ifelse } {dup dup 0 get findfont exch 1 get scalefont setfont [ currentpoint ] exch dup 2 get 0 exch R dup 5 get 2 ne {dup dup 6 get exch 4 get {show} {stringwidth pop 0 R} ifelse }if dup 5 get 0 eq {dup 3 get {2 get neg 0 exch R pop} {pop aload pop M} ifelse} {dup 5 get 1 eq {dup 2 get exch dup 3 get exch 6 get stringwidth pop -2 div dup 0 R} {dup 6 get stringwidth pop -2 div 0 R 6 get show 2 index {aload pop M neg 3 -1 roll neg R pop pop} {pop pop pop pop aload pop M} ifelse }ifelse }ifelse } ifelse } forall} bind def /MFwidth {0 exch { dup 5 get 3 ge { 5 get 3 eq { 0 } { pop } ifelse } {dup 3 get{dup dup 0 get findfont exch 1 get scalefont setfont 6 get stringwidth pop add} {pop} ifelse} ifelse} forall} bind def /MLshow { currentpoint stroke M 0 exch R Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def /MRshow { currentpoint stroke M exch dup MFwidth neg 3 -1 roll R Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def /MCshow { currentpoint stroke M exch dup MFwidth -2 div 3 -1 roll R Blacktext {gsave 0 setgray MFshow grestore} {MFshow} ifelse } bind def /XYsave { [( ) 1 2 true false 3 ()] } bind def /XYrestore { [( ) 1 2 true false 4 ()] } bind def end %%EndProlog gnudict begin gsave 50 50 translate 0.050 0.050 scale 0 setgray newpath (Helvetica) findfont 140 scalefont setfont gsave % colour palette begin /maxcolors 64 def /HSV2RGB { exch dup 0.0 eq {pop exch pop dup dup} % achromatic gray { /HSVs exch def /HSVv exch def 6.0 mul dup floor dup 3 1 roll sub /HSVf exch def /HSVi exch cvi def /HSVp HSVv 1.0 HSVs sub mul def /HSVq HSVv 1.0 HSVs HSVf mul sub mul def /HSVt HSVv 1.0 HSVs 1.0 HSVf sub mul sub mul def /HSVi HSVi 6 mod def 0 HSVi eq {HSVv HSVt HSVp} {1 HSVi eq {HSVq HSVv HSVp}{2 HSVi eq {HSVp HSVv HSVt} {3 HSVi eq {HSVp HSVq HSVv}{4 HSVi eq {HSVt HSVp HSVv} {HSVv HSVp HSVq} ifelse} ifelse} ifelse} ifelse} ifelse } ifelse} def /Constrain { dup 0 lt {0 exch pop}{dup 1 gt {1 exch pop} if} ifelse} def /YIQ2RGB { 3 copy -1.702 mul exch -1.105 mul add add Constrain 4 1 roll 3 copy -0.647 mul exch -0.272 mul add add Constrain 5 1 roll 0.621 mul exch -0.956 mul add add Constrain 3 1 roll } def /CMY2RGB { 1 exch sub exch 1 exch sub 3 2 roll 1 exch sub 3 1 roll exch } def /XYZ2RGB { 3 copy -0.9017 mul exch -0.1187 mul add exch 0.0585 mul exch add Constrain 4 1 roll 3 copy -0.0279 mul exch 1.999 mul add exch -0.9844 mul add Constrain 5 1 roll -0.2891 mul exch -0.5338 mul add exch 1.91 mul exch add Constrain 3 1 roll} def /SelectSpace {ColorSpace (HSV) eq {HSV2RGB}{ColorSpace (XYZ) eq { XYZ2RGB}{ColorSpace (CMY) eq {CMY2RGB}{ColorSpace (YIQ) eq {YIQ2RGB} if} ifelse} ifelse} ifelse} def /InterpolatedColor true def /grayindex {/gidx 0 def {GrayA gidx get grayv ge {exit} if /gidx gidx 1 add def} loop} def /dgdx {grayv GrayA gidx get sub GrayA gidx 1 sub get GrayA gidx get sub div} def /redvalue {RedA gidx get RedA gidx 1 sub get RedA gidx get sub dgdxval mul add} def /greenvalue {GreenA gidx get GreenA gidx 1 sub get GreenA gidx get sub dgdxval mul add} def /bluevalue {BlueA gidx get BlueA gidx 1 sub get BlueA gidx get sub dgdxval mul add} def /interpolate { grayindex grayv GrayA gidx get sub abs 1e-5 le {RedA gidx get GreenA gidx get BlueA gidx get} {/dgdxval dgdx def redvalue greenvalue bluevalue} ifelse} def /GrayA [0 .0159 .0317 .0476 .0635 .0794 .0952 .1111 .127 .1429 .1587 .1746 .1905 .2063 .2222 .2381 .254 .2698 .2857 .3016 .3175 .3333 .3492 .3651 .381 .3968 .4127 .4286 .4444 .4603 .4762 .4921 .5079 .5238 .5397 .5556 .5714 .5873 .6032 .619 .6349 .6508 .6667 .6825 .6984 .7143 .7302 .746 .7619 .7778 .7937 .8095 .8254 .8413 .8571 .873 .8889 .9048 .9206 .9365 .9524 .9683 .9841 1 ] def /RedA [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .0238 .0873 .1508 .2143 .2778 .3413 .4048 .4683 .5317 .5952 .6587 .7222 .7857 .8492 .9127 .9762 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .9444 .881 .8175 .754 .6905 .627 .5635 .5 ] def /GreenA [0 0 0 0 0 0 0 0 .0079 .0714 .1349 .1984 .2619 .3254 .3889 .4524 .5159 .5794 .6429 .7063 .7698 .8333 .8968 .9603 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .9603 .8968 .8333 .7698 .7063 .6429 .5794 .5159 .4524 .3889 .3254 .2619 .1984 .1349 .0714 .0079 0 0 0 0 0 0 0 0 ] def /BlueA [.5 .5635 .627 .6905 .754 .8175 .881 .9444 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 .9762 .9127 .8492 .7857 .7222 .6587 .5952 .5317 .4683 .4048 .3413 .2778 .2143 .1508 .0873 .0238 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] def /pm3dround {maxcolors 0 gt {dup 1 ge {pop 1} {maxcolors mul floor maxcolors 1 sub div} ifelse} if} def /pm3dGamma 1.0 1.5 div def /ColorSpace (RGB) def Color true and { % COLOUR vs. GRAY map InterpolatedColor { %% Interpolation vs. RGB-Formula /g {stroke pm3dround /grayv exch def interpolate SelectSpace setrgbcolor} bind def }{ /g {stroke pm3dround dup cF7 Constrain exch dup cF5 Constrain exch cF15 Constrain SelectSpace setrgbcolor} bind def } ifelse }{ /g {stroke pm3dround pm3dGamma exp setgray} bind def } ifelse 0.500 UL LTb 1.000 UL LTa 406 280 M 6556 0 V stroke 0.500 UL LTb 406 280 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 280 M [ [(Helvetica) 140.0 0.0 true true 0 (-7)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 790 M 6556 0 V stroke 0.500 UL LTb 406 790 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 790 M [ [(Helvetica) 140.0 0.0 true true 0 (-6)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 1300 M 6556 0 V stroke 0.500 UL LTb 406 1300 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 1300 M [ [(Helvetica) 140.0 0.0 true true 0 (-5)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 1811 M 6556 0 V stroke 0.500 UL LTb 406 1811 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 1811 M [ [(Helvetica) 140.0 0.0 true true 0 (-4)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 2321 M 6556 0 V stroke 0.500 UL LTb 406 2321 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 2321 M [ [(Helvetica) 140.0 0.0 true true 0 (-3)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 2831 M 6556 0 V stroke 0.500 UL LTb 406 2831 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 2831 M [ [(Helvetica) 140.0 0.0 true true 0 (-2)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 3341 M 6556 0 V stroke 0.500 UL LTb 406 3341 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 3341 M [ [(Helvetica) 140.0 0.0 true true 0 (-1)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 3852 M 6556 0 V stroke 0.500 UL LTb 406 3852 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 3852 M [ [(Helvetica) 140.0 0.0 true true 0 (0)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 4362 M 5233 0 V 1239 0 R 84 0 V stroke 0.500 UL LTb 406 4362 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 4362 M [ [(Helvetica) 140.0 0.0 true true 0 (1)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 406 4872 M 6556 0 V stroke 0.500 UL LTb 406 4872 M 63 0 V 6493 0 R -63 0 V stroke 0.00 0.00 0.00 C 322 4872 M [ [(Helvetica) 140.0 0.0 true true 0 (2)] ] -46.7 MRshow 0.500 UL LTb 1.000 UL LTa 1062 280 M 0 4592 V stroke 0.500 UL LTb 1062 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 1062 140 M [ [(Helvetica) 140.0 0.0 true true 0 (60)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 2373 280 M 0 4592 V stroke 0.500 UL LTb 2373 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 2373 140 M [ [(Helvetica) 140.0 0.0 true true 0 (80)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 3684 280 M 0 4592 V stroke 0.500 UL LTb 3684 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 3684 140 M [ [(Helvetica) 140.0 0.0 true true 0 (100)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 4995 280 M 0 4592 V stroke 0.500 UL LTb 4995 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 4995 140 M [ [(Helvetica) 140.0 0.0 true true 0 (120)] ] -46.7 MCshow 0.500 UL LTb 1.000 UL LTa 6306 280 M 0 3969 V 0 560 R 0 63 V stroke 0.500 UL LTb 6306 280 M 0 63 V 0 4529 R 0 -63 V stroke 0.00 0.00 0.00 C 6306 140 M [ [(Helvetica) 140.0 0.0 true true 0 (140)] ] -46.7 MCshow 0.500 UL LTb 0.500 UL LTb 406 4872 N 406 280 L 6556 0 V 0 4592 V -6556 0 V Z stroke 1.000 UP 0.500 UL LTb 1.000 UP 0.500 UL LT0 0.00 0.00 1.00 C LTb 6311 4739 M [ [(Helvetica) 140.0 0.0 true true 0 (Points)] ] -46.7 MRshow LT0 0.00 0.00 1.00 C 1717 3852 Star 2045 3852 Star 2373 3852 Star 3356 1300 Star 3684 1300 Star 4012 1300 Star 4995 3852 Star 5323 3852 Star 5651 3852 Star 6594 4739 Star 0.500 UL LT1 0.00 0.50 0.00 C LTb 6311 4599 M [ [(Helvetica) 140.0 0.0 true true 0 (Lin)] ] -46.7 MRshow LT1 0.00 0.50 0.00 C 6395 4599 M 399 0 V 1717 3852 M 328 0 V 328 0 V 3356 1300 L 328 0 V 328 0 V 983 2552 V 328 0 V 328 0 V stroke LT2 1.00 0.00 0.00 C LTb 6311 4459 M [ [(Helvetica) 140.0 0.0 true true 0 (B-Spline)] ] -46.7 MRshow LT2 1.00 0.00 0.00 C 6395 4459 M 399 0 V 1717 3852 M 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 -1 V 8 0 V 8 0 V 8 0 V 8 -1 V 8 -1 V 8 -1 V 9 -1 V 8 -2 V 8 -2 V 9 -3 V 8 -3 V 9 -3 V 9 -4 V 9 -5 V 9 -5 V 10 -5 V 9 -7 V 10 -7 V 10 -8 V 10 -8 V 10 -9 V 11 -11 V 10 -11 V 11 -11 V 11 -13 V 12 -14 V 12 -15 V 12 -16 V 12 -17 V 12 -18 V 13 -19 V 13 -21 V 14 -21 V 13 -23 V 15 -24 V 14 -26 V 15 -27 V 15 -28 V 15 -30 V 7 -13 V 6 -11 V 5 -10 V 6 -11 V 5 -11 V 5 -11 V 6 -11 V 5 -12 V 6 -11 V 6 -12 V 5 -11 V 6 -12 V 6 -12 V 5 -13 V 6 -12 V 6 -12 V 6 -13 V 6 -13 V 6 -12 V 2594 3195 L 6 -13 V 6 -13 V 6 -14 V 6 -13 V 6 -13 V 6 -14 V 6 -14 V 6 -13 V 6 -14 V 7 -14 V 6 -14 V 6 -14 V 6 -14 V 7 -14 V 6 -15 V 6 -14 V 7 -15 V 6 -14 V 6 -15 V 7 -14 V 6 -15 V 7 -15 V 6 -15 V 6 -14 V 7 -15 V 6 -15 V 7 -15 V 6 -15 V 7 -15 V 6 -16 V 7 -15 V 6 -15 V 7 -15 V 6 -15 V 7 -16 V 7 -15 V 6 -15 V 7 -15 V 6 -16 V 7 -15 V 6 -15 V 7 -16 V 7 -15 V 6 -15 V 7 -16 V 6 -15 V 7 -15 V 6 -16 V 7 -15 V 6 -15 V 7 -15 V 7 -16 V 6 -15 V 7 -15 V 6 -15 V 7 -15 V 6 -15 V 7 -15 V 6 -15 V 7 -15 V 6 -15 V 6 -15 V 7 -15 V 6 -15 V 7 -14 V 6 -15 V 7 -15 V 6 -14 V 6 -15 V 7 -14 V 6 -14 V 6 -15 V 6 -14 V 7 -14 V 6 -14 V 6 -14 V 6 -14 V 6 -13 V 7 -14 V 6 -13 V 6 -14 V 6 -13 V 6 -14 V 6 -13 V 6 -13 V 6 -13 V 6 -12 V 6 -13 V 5 -13 V 6 -12 V 6 -12 V 6 -13 V 6 -12 V 5 -12 V 6 -11 V 5 -12 V 6 -12 V 6 -11 V 5 -11 V 6 -11 V 5 -11 V 5 -11 V 6 -10 V 5 -11 V 3248 1723 L 16 -30 V 15 -28 V 15 -27 V 14 -26 V 14 -24 V 14 -23 V 14 -22 V 13 -20 V 13 -20 V 12 -18 V 12 -17 V 12 -16 V 12 -15 V 12 -14 V 11 -13 V 11 -12 V 11 -11 V 10 -10 V 10 -9 V 10 -9 V 10 -8 V 10 -7 V 10 -6 V 9 -6 V 9 -5 V 9 -5 V 9 -4 V 9 -3 V 8 -3 V 9 -3 V 8 -2 V 9 -1 V 8 -2 V 8 -1 V 8 -1 V 8 -1 V 8 0 V 8 0 V 8 0 V 8 -1 V 8 0 V 8 0 V 8 0 V 8 1 V 8 0 V 8 0 V 8 0 V 8 1 V 8 1 V 8 1 V 8 2 V 9 1 V 8 2 V 9 3 V 8 3 V 9 3 V 9 4 V 9 5 V 9 5 V 9 6 V 10 6 V 10 7 V 10 8 V 10 9 V 10 9 V 10 10 V 11 11 V 11 12 V 11 13 V 12 14 V 12 15 V 12 16 V 12 17 V 12 18 V 13 20 V 13 20 V 14 22 V 14 23 V 14 24 V 14 26 V 15 27 V 15 28 V 16 30 V 6 12 V 5 11 V 6 10 V 5 11 V 5 11 V 6 11 V 5 11 V 6 11 V 6 12 V 5 12 V 6 11 V 5 12 V 6 12 V 6 13 V 6 12 V 6 12 V 5 13 V 6 13 V 6 12 V 6 13 V 6 13 V 4245 1984 L 6 14 V 6 13 V 6 14 V 6 13 V 7 14 V 6 13 V 6 14 V 6 14 V 6 14 V 7 14 V 6 14 V 6 15 V 6 14 V 7 14 V 6 15 V 6 14 V 7 15 V 6 15 V 7 14 V 6 15 V 7 15 V 6 15 V 6 15 V 7 15 V 6 15 V 7 15 V 6 15 V 7 15 V 6 15 V 7 15 V 6 15 V 7 16 V 7 15 V 6 15 V 7 15 V 6 16 V 7 15 V 6 15 V 7 16 V 6 15 V 7 15 V 7 16 V 6 15 V 7 15 V 6 16 V 7 15 V 6 15 V 7 15 V 7 16 V 6 15 V 7 15 V 6 15 V 7 15 V 6 16 V 7 15 V 6 15 V 7 15 V 6 15 V 7 15 V 6 14 V 6 15 V 7 15 V 6 15 V 7 14 V 6 15 V 6 14 V 7 15 V 6 14 V 6 15 V 7 14 V 6 14 V 6 14 V 6 14 V 7 14 V 6 14 V 6 13 V 6 14 V 6 14 V 6 13 V 6 13 V 6 14 V 6 13 V 6 13 V 6 13 V 6 12 V 6 13 V 6 13 V 6 12 V 6 12 V 5 13 V 6 12 V 6 12 V 5 11 V 6 12 V 6 11 V 5 12 V 6 11 V 5 11 V 5 11 V 6 11 V 5 10 V 6 11 V 7 13 V 15 30 V 4919 3489 L 15 27 V 14 26 V 15 24 V 13 23 V 14 21 V 13 21 V 13 19 V 12 18 V 12 17 V 12 16 V 12 15 V 12 14 V 11 13 V 11 11 V 10 11 V 11 11 V 10 9 V 10 8 V 10 8 V 10 7 V 9 7 V 10 5 V 9 5 V 9 5 V 9 4 V 9 3 V 8 3 V 9 3 V 8 2 V 8 2 V 9 1 V 8 1 V 8 1 V 8 1 V 8 0 V 8 0 V 8 0 V 8 1 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V stroke LT3 0.00 0.75 0.75 C LTb 6311 4319 M [ [(Helvetica) 140.0 0.0 true true 0 (PCHIP)] ] -46.7 MRshow LT3 0.00 0.75 0.75 C 6395 4319 M 399 0 V 1717 3852 M 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 -1 V 8 -1 V 8 -2 V 8 -4 V 8 -4 V 8 -5 V 8 -6 V 8 -6 V 7 -8 V 8 -8 V 8 -10 V 8 -10 V 8 -11 V 8 -12 V 8 -12 V 8 -13 V 7 -14 V 8 -15 V 8 -15 V 2529 3679 L 8 -17 V 8 -18 V 8 -18 V 8 -18 V 8 -19 V 7 -20 V 8 -21 V 8 -21 V 8 -21 V 8 -22 V 8 -23 V 8 -23 V 8 -24 V 8 -24 V 7 -24 V 8 -25 V 8 -25 V 8 -26 V 8 -26 V 8 -27 V 8 -26 V 8 -28 V 7 -27 V 8 -28 V 8 -28 V 8 -28 V 8 -29 V 8 -29 V 8 -29 V 8 -29 V 8 -30 V 7 -30 V 8 -30 V 8 -30 V 8 -30 V 8 -30 V 8 -30 V 8 -31 V 8 -30 V 7 -31 V 8 -31 V 8 -30 V 8 -31 V 8 -31 V 8 -30 V 8 -31 V 8 -31 V 8 -30 V 7 -30 V 8 -31 V 8 -30 V 8 -30 V 8 -30 V 8 -30 V 8 -29 V 8 -29 V 7 -30 V 8 -28 V 8 -29 V 8 -29 V 8 -28 V 8 -28 V 8 -27 V 8 -27 V 8 -27 V 7 -27 V 8 -26 V 8 -26 V 8 -25 V 8 -25 V 8 -24 V 8 -24 V 8 -24 V 7 -23 V 8 -23 V 8 -22 V 8 -21 V 8 -22 V 8 -20 V 8 -20 V 8 -19 V 8 -19 V 7 -18 V 8 -17 V 8 -17 V 8 -16 V 8 -16 V 8 -15 V 8 -14 V 8 -13 V 7 -12 V 8 -12 V 8 -11 V 8 -10 V 8 -10 V 8 -8 V 8 -8 V 8 -7 V 8 -6 V 7 -5 V 8 -4 V 8 -3 V 8 -3 V 8 -1 V 3357 1300 L 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 1 V 8 1 V 8 3 V 8 3 V 8 4 V 7 5 V 8 6 V 8 7 V 8 8 V 8 8 V 8 10 V 8 10 V 8 11 V 8 12 V 7 12 V 8 13 V 8 14 V 8 15 V 8 16 V 8 16 V 8 17 V 4185 1509 L 7 18 V 8 19 V 8 19 V 8 20 V 8 20 V 8 22 V 8 21 V 8 22 V 8 23 V 7 23 V 8 24 V 8 24 V 8 24 V 8 25 V 8 25 V 8 26 V 8 26 V 7 27 V 8 27 V 8 27 V 8 27 V 8 28 V 8 28 V 8 29 V 8 29 V 8 28 V 7 30 V 8 29 V 8 29 V 8 30 V 8 30 V 8 30 V 8 30 V 8 31 V 7 30 V 8 30 V 8 31 V 8 31 V 8 30 V 8 31 V 8 31 V 8 30 V 8 31 V 7 31 V 8 30 V 8 31 V 8 30 V 8 30 V 8 30 V 8 30 V 8 30 V 7 30 V 8 30 V 8 29 V 8 29 V 8 29 V 8 29 V 8 28 V 8 28 V 8 28 V 7 27 V 8 28 V 8 26 V 8 27 V 8 26 V 8 26 V 8 25 V 8 25 V 7 24 V 8 24 V 8 24 V 8 23 V 8 23 V 8 22 V 8 21 V 8 21 V 8 21 V 7 20 V 8 19 V 8 18 V 8 18 V 8 18 V 8 17 V 8 16 V 8 15 V 8 15 V 7 14 V 8 13 V 8 12 V 8 12 V 8 11 V 8 10 V 8 10 V 8 8 V 7 8 V 8 6 V 8 6 V 8 5 V 8 4 V 8 4 V 8 2 V 8 1 V 8 1 V 7 0 V 5012 3852 L 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V 7 0 V 8 0 V 8 0 V 8 0 V 8 0 V 8 0 V stroke LTb 406 4872 N 406 280 L 6556 0 V 0 4592 V -6556 0 V Z stroke 1.000 UP 0.500 UL LTb stroke grestore end showpage %%Trailer %%DocumentFonts: Helvetica drc-3.2.2/source/doc/genpng0000644000076400001450000000045513163167105014526 0ustar denisitadm#!/bin/sh # Create the PNG version of all eps files for file in figures/*.eps do pngfile=$(basename "$file" .eps) echo "$file" '->' "${pngfile}.png" gs -q -dEPSFitPage -g1024x768 -dNOPAUSE -dBATCH -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=png16m -sOutputFile="${pngfile}.png" "$file" done drc-3.2.2/source/doc/drc.tex0000644000076400001450000062010213163167414014617 0ustar denisitadm% DRC: Digital Room Correction % User manual % % Copyright (C) 2002-2017 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@neomerica.it % % This program uses the FFT routines from Takuya Ooura and the GNU % Scientific Library (GSL) FFT routines. Many thanks to Takuya Ooura and % the GSL developers for these efficient routines. % Definizione stile documento \documentclass[a4paper,titlepage]{article} \pagestyle{headings} % Pacchetti aggiuntivi \usepackage{url} \usepackage{graphicx} \usepackage{tocloft} \usepackage[pdftitle={DRC: Digital Room Correction},pdfauthor={Denis Sbragion}, a4paper,pdfstartview=FitH,plainpages=false,pdfpagelabels, colorlinks=true,bookmarks=true,bookmarksnumbered,linktocpage]{hyperref} % Incrementa lo spazio per la numerazione nella tavola dei contenuti \addtolength{\cftsubsubsecnumwidth}{0.5em} % Dimensione figure \newcommand{\basepctwidth}{0.9} \newcommand{\pctwidth}{1.0} % Definizione titolo \title{DRC: Digital Room Correction} \author{Denis Sbragion} \date{ 2017-10-01 \linebreak\linebreak \small{Copyright \copyright\ 2002-2017 Denis Sbragion} \linebreak\linebreak \small{Version 3.2.2} } % Inizio documento \begin{document} % Imposta il page numbering a roman per la pagina del titolo \pagenumbering{roman} % Pagina con il titolo \begin{titlepage} \maketitle\thispagestyle{empty} \end{titlepage} % Reimposta il page numbering a arabic per le pagine rimanenti \pagenumbering{arabic} % Pagina con la licenza GPL \thispagestyle{empty} {\sf \noindent 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. \medskip \noindent 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. \medskip \noindent 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. \medskip \noindent You can contact the author on Internet at the following address: \begin{quote} \url{d.sbragion@neomerica.it} \end{quote} \noindent This program uses the FFT routines from Takuya Ooura and the GNU Scientific Library (GSL) FFT routines. Many thanks to Takuya Ooura and the GSL developers for these efficient routines. } % Salto pagina tavola dei contenuti \clearpage %Tavola contenuti \tableofcontents % Salto pagina lista figure \clearpage % Lista figure \listoffigures % Salto pagina inizio manuale \clearpage % Introduzione \section{Introduction} DRC uses a lot of signal, linear system and DSP theory to achieve its results. In this user manual some knowledge about those arguments is assumed. I'm planning to write a more extensive manual with the basics needed to understand what DRC does, or at least is trying to do, but unfortunately I have just little spare time to dedicate to this project, so I will concentrate just on improving the program performances. Of course volunteers, suggestion, patches, better documentation, pointers and references on the subject are all appreciated. For a basic introductory guide to DSP theory and practice you might look at: \begin{quote} \url{http://www.dspguide.com/} \end{quote} For a basic introduction to DSP applied to audio you might read the good book available at: \begin{quote} \sloppy\raggedright \url{https://archive.org/details/IntroductionToSoundProcessing} \end{quote} To better understand what DRC is trying to do you might look at: \begin{quote} \url{https://en.wikipedia.org/wiki/Digital_room_correction} \end{quote} This clear and concise Wikipedia article contains all the basics needed to understand digital room correction in general. In order to measure the room impulse response and to perform real time or offline convolution (i.e. the correction) of the digital signal, you have to use some external programs, like, for example, Room Eq Wizard and BruteFIR (see sections \ref{RoomEqWizard} and \ref{BruteFIR}). % Riferimenti \section{Getting the latest version} The official DRC web site is available at the following address: \begin{quote} \url{http://drc-fir.sourceforge.net/} \end{quote} On the web site you will always find news and up to date informations, the full documentation for the latest version, informations about where to download it and many other DRC related informations. % Nuove funzionalit \section{What's new in version 3.2.2} Minor changes and bug corrections. General documentation clean-up. Default compilation switched to double precision arithmetic. The GSL FFT libraries have been updated to the latest release. \subsection{Compatibility with previous versions} Configuration files for version 3.2.2 are compatible with the previous version. % Modifiche precedenti \subsection{History: what was new in previous versions} \subsubsection{Version 3.2.1} Minor accuracy improvements and minor changes to the default configuration templates have been introduced. Configuration file handling now is performed using the minIni library instead of the parsecfg library. A minor bug in the axis labeling of the Morlet cycle/octave scalograms has been corrected. The plot generation scripts have been reworked for better readability, better axis labeling and compatibility with the latest version of Octave. \subsubsection{Version 3.2.0} A new computation of the RMS value based on a logarithmic frequency weighting of the magnitude response has been introduced. This new method allow for a better handling of the filter magnitude response peak limiting. A bug in the extimation of the band limited RMS value has been also corrected. Some other procedures have been refined in order to provide an improved accuracy. The glsweep and lsconv tools have been reworked to provide correct reference levels thus allowing for SPL calibrated measurements. \subsubsection{Version 3.1.1} The licensing of some file has been corrected. Minor corrections and accuracy improvements. \subsubsection{Version 3.1.0} The Octave scripts have been reworked to make them compatible with the latest version of Octave and improved to provide some autoscaling features and exports to different image formats. The microphone compensation stage has been moved to the beginning of the correction procedure so that any following stage works using the compensated impulse response as a reference. A new parameter adding a configurable delay to the minimum phase version of the correction filter has been introduced. Many other minor bugs have been fixed. \subsubsection{Version 3.0.1} The Octave scripts have been reworked to make them compatible with version 3 of Octave. A new renormalization procedure, providing a reasonable extimation of clipping levels, has been added. Many minor bugs have been fixed. \subsubsection{Version 3.0.0} A new method for the computation of an optimized psychoacoustic target response, based on the spectral envelope of the corrected impulse response, has been introduced. \subsubsection{Version 2.7.0} A new method for the computation of the excess phase component inverse, based on a simple time reversal, has been introduced. The sample configuration files have been rewritten to take advantage of the new inversion procedure. Sample configuration files for 48 kHz, 88.2 kHz, 96 kHz sample rates have been added. The homomorphic deconvolution procedure has been improved to avoid any numerical instability. A new Piecewise Cubic Hermite Interpolating Polynomial (PCHIP) interpolation method, providing monotonic behaviour, has been introduced in the target response computation. All the interpolation and approximation procedures have been rewritten from scratch to provide better performances and accuracy. \subsubsection{Version 2.6.2} A new command line parameters replacement functionality has been introduced. The dip and peak limiting procedures have been improved in order to avoid numerical instabilities. A new wavelet based analysis graph has been added to the sample results. Many performance improvements have been introduced. A new optional parameter used to define the base directory for all files has been added. \subsubsection{Version 2.6.1} Minor corrections and improvements have been applied to the documentation and to the pre-echo truncation inversion procedure. A new target transfer function definition procedure based on Uniform B Splines has been introduced. The development environment has been moved to Code::Blocks and GCC/MinGW. \subsubsection{Version 2.6.0} A new prefiltering curve based on the bilinear transformation has been introduced. An improved windowing of the minimum phase filters used to apply the target frequency response and the microphone compensation has been implemented. A missing normalization of the minimum phase correction filter has been added. A new logarithmic interpolation has been added to the target transfer function computation. The new interpolation method simplifies the definition of the target transfer functions. Small improvements to the documentation and to the Octave scripts used to generate the graphs have been applied. A new improved version of the measurejack script has been included in the package. Some new sample configuration files, including one approximating the ERB psychoacoustic scale, have been added. \subsubsection{Version 2.5.1} Small improvements to the documentation and to the Octave scripts used to generate the graphs. The sliding lowpass prefiltering procedure has been rewritten to make it a bit more accurate and to make the code more readable. Few other minor bugs have been fixed. \subsubsection{Version 2.5.0} With version 2.5.0 a general overhauling of the filter generation procedure has been performed. Some steps (peak limiting for example) have been moved to a different stage of the procedure, and new stages have been added. A new ringing truncation stage has been added to remove excessive ringing caused sometimes by the pre-echo truncation procedure. Now the filter impulse response is enclosed in a sort of psychoacoustic jail that prevent, or at least reduces a lot, any artifact that could arise as a side effect of the filter generation procedure. With this changes DRC becomes somewhat ``self tuning'' and now it is able to adapt itself to the input impulse response, at least to some extent, providing as much correction as possible without generating excessive artifacts. The postfiltering stage, where the target transfer function is defined, has been split to provide a separate stage for microphone compensation. This allows for a greater flexibility defining both the target transfer function and the microphone compensation, and provides as a side effect correct test convolutions even when microphone compensation is in place. With the previous versions the test convolution was improperly altered by the microphone compensation, because both the target transfer function and the microphone compensation were generated and applied using the same filter. Many other procedures have been refined. For example the peak and dip limiting procedures now ensure continuity up to the first derivative of the magnitude response on the points where the magnitude limiting starts its effect. This further reduces the ringing caused by abrupt changes in the magnitude response. Finally many other minor bugs have been corrected and the documentation has been improved, switching to \LaTeX\ for document generation and formatting. \subsubsection{Version 2.4.2} Version 2.4.2 added a better handling of underflow problems during homomorphic deconvolution. Some little speed improvements have been also achieved. Added search and output of peak value and peak position into lsconv. \subsubsection{Version 2.4.1} Version 2.4.1 added some tools for accurate time aligned impulse response measurements. This make it possible to compensate for interchannel misalignments, at least up to a limited extent. Some minor bugs have been also corrected. \subsubsection{Version 2.4.0} In version 2.4.0 the Takuya Ooura and GNU Scientific Library FFT routines have been included in the program. These routines are about 10 times faster than the previous routines, providing about the same accuracy. Furthermore some checks have been added to the sharpness parameters to avoid program crashes when these parameters are missing. The FFT routines described above are available at: \begin{itemize} \sloppy\raggedright \item \url{http://www.gnu.org/software/gsl/} \item \url{http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html} \end{itemize} \subsubsection{Version 2.3.2} In version 2.3.2 a new sharpness factor parameter has been added to the sliding low pass prefiltering procedure. This parameter provides a control between filtering sharpness and spectral spreading in the filter transition region. A new option to read and write double precision floating points files has been added. Some checks to warn when the input signal is too short to provide accurate results has been added. \subsubsection{Version 2.3.1} In version 2.3.1 some minor corrections to the program have been performed and the documentation has been restructured. A new option to automatically count the number of lines in the target function and microphone compensation files has been added. A new optimized sample configuration file has been added. \subsubsection{Version 2.3.0} Version 2.3.0 adds two parameters to control the gain limiting procedures. These parameters control a sort of ``soft clipping'' of the frequency response, avoiding ringing on abrupt truncations of the frequency response. A new parameter to select the magnitude type, either linear or expressed in dB, of the target frequency response has been added. The optional capability to perform microphone compensation has also been added. The license has been switched to the GNU GPL. \subsubsection{Version 2.2.0} Version 2.2.0 added a sliding low pass procedure to the pre-echo truncation inversion procedure. This pre-echo truncation procedure is much more similar to the pre-echo sensitivity of our hear and so slightly better results are achieved. Furthermore the sliding low pass prefiltering procedure has been completely rewritten to provide better accuracy, especially with the short window lengths needed for pre-echo truncation. \subsubsection{Version 2.1.0} Version 2.1.0 added two new parameters that allow for the windowing of everything coming more than few samples before the impulse center. Usually before the main spike there's only noise and spuriae. I have found that in certain situations this small noise may lead to audible errors in the correction, so windowing it out in order to clean the impulse response is a good practice. \subsubsection{Version 2.0.0} \label{Version-2.0.0} Version 2.0.0 added many new features that provides much better control on pre-echo artifacts problems. The most important change is the new pre-echo truncation inversion procedure. Loosely derived from Kirkeby fast deconvolution this new procedure truncates any pre-echo on the excess phase part inversion. This leads to something like minimum phase inversion on frequency ranges where a complete inversion would lead to pre-echo artifacts. This critical frequency ranges are usually no more than 5 or 6 and no wider than about 1/12 of octave for a typical room impulse response. Reducing the correction to minimum phase on so narrow bands has little or no subjective effect on the correction quality and allows for the correction of much longer windows, with much better overall results. Avoiding pre-echo artifacts also provides the ability to create low input-output delay filters. The resulting delay is often low enough (few ms) to allow the use of these filters in home theater applications. For situations where even few ms aren't adequate there's now also an option to generate zero delay minimum phase filters. Minimum phase filters provides correction of the amplitude response and just the minimum phase part of the phase response. In order to avoid pre-echo artifacts there are also many other aspects that should be taken into account. For a better explanation of the whole procedure and the selection method for the DRC parameters needed to achieve this result look at the section \ref{AvoidPreEchoArtifacts}. Version 2.0.0 adds also many other improvements, including the single side version of the prefiltering procedures and fixing for many minor bugs that where still laying around. A test convolution stage is now also available. This convolves the input impulse response with the generated filter to get the impulse response after correction. The impulse response obtained by this method is usually really reliable. As long as the measurement microphone isn't moved I have been able to verify the computed impulse response with less than $0.5$ dB errors, which is impressive considering the cheap measurement set I use. In my situation may be that the computed corrected impulse response is even more accurate than the measured one, because of noise problems being doubled by my cheap measurement set in the second measure. \subsubsection{Version 1.3.0} Version 1.3.0 provided some new features with respect to version 1.2.1: \begin{itemize} \item More flexible prefiltering curve parameters \item New time varying sliding lowpass prefiltering stage \item New minimum phase or homomorphic renormalization of the prefiltered excess phase component \item Homomorphic deconvolution based on the Hilbert transform instead of the cepstrum method \item Slightly improved documentation \item Many minor bugs fixed \end{itemize} \section{Program description and operation} DRC is a program used to generate correction filters for acoustic compensation of HiFi and audio systems in general, including listening room compensation. DRC generates just the FIR correction filters, which must be used with a real time or offline convolver to provide real time or offline correction. DRC doesn't provide convolution features, and provides only some simplified, although really accurate, measuring tools. So in order to use DRC you need: \begin{enumerate} \item At least 1 second of the impulse response of your room and audio system at the listening position, separated for each channel, which means usually just left and right for a basic HiFi system. The impulse response should be provided in raw format (flat file with just samples, no headers or additional information whatsoever), either in signed 16 bit format or using 32/64 bit IEEE floating point samples. From version 2.4.1 DRC includes some command line tools to do accurate time aligned impulse response measurement, see section \ref{ImpulseResponseMeasurement} for further details. Many other systems, either commercial or free, are available on the Internet to carry out this task. Take a look at: \begin{itemize} \sloppy\raggedright \item \label{RoomEqWizard} Room Eq Wizard \url{http://www.hometheatershack.com/roomeq/} \item AcourateLSR2: \url{http://www.audiovero.de/} \item Aurora plugins: \url{http://www.aurora-plugins.com/} \item CLIO: \url{http://www.audiomatica.it/} \end{itemize} Since some time there are also some integrated packages provinding both the measurements functionality and the correction, based on DRC. Some examples: \begin{itemize} \sloppy\raggedright \item DRCDesigner: \url{http://www.alanjordan.org/DRCDesigner/DrcDesignerHelp.html} \item Align: \url{http://www.ohl.to/about-audio/audio-softwares/align/} \item The Final Cut: \url{http://www.ohl.to/about-audio/audio-softwares/the-final-cut/} \end{itemize} This packages may be really useful, expecially for unexperienced peoples. Of course a good instrumentation microphone and preamplifier are needed to get accurate measurements of your listening room response. The ETF web sites has a link to a cheap but still quite good instrumentation microphone, which comes with an individual calibration file: \begin{quote} \url{http://www.isemcon.net/} \end{quote} It is built around the Panasonic electrect capsules (WM-60A and WM-61A) which can be used also to build a DIY microphone. Of course you won't get the same quality of a professional instrumentation microphone, but it is enough to get good results. Some other good and inexpensive solutions are the Behringer ECM8000 measurement microphone (see \url{http://www.behringer.com} for details) and the Dayton Audio EMM-6: \begin{quote} \url{http://www.daytonaudio.com/index.php/emm-6-electret-measurement-microphone.html} \end{quote} which provides also individual calibration files. \item A real time convolver able to deal with FIR filters with at least 4000 and up to more than 32000 taps, like BruteFIR, Foobar2000, the ActiveX Convolver Plugin and others. References for these programs can be found at the following links: \label{BruteFIR} \begin{itemize} \sloppy\raggedright \item BruteFIR: \url{http://www.ludd.luth.se/~torger/brutefir.html} \item ActiveX Convolver Plugin: \url{http://convolver.sourceforge.net} \item Foobar2000 with convolver plugin: \url{http://www.foobar2000.org/} \item Jconvolver: \url{http://kokkinizita.linuxaudio.org/linuxaudio/} \item Aurora plugins: \url{http://www.aurora-plugins.com/} \end{itemize} Furthermore a ready to use Linux distribution suited for audio applications is available at Planet CCRMA: \begin{quote} \url{http://ccrma.stanford.edu/planetccrma/software/} \end{quote} This distribution already contains most of what is needed to create a real time convolution engine suited for digital room correction. \item Hardware needed to run all the software. Almost any modern personal computer has enough computational power to run the convolution in realtime without any problem. Today there are many good, silent and compact PCs designed for multimedia usage which could be used to build a complete noiseless real time convolver with little effort. \end{enumerate} Of course to test the program you can also apply the correction off-line on audio files ripped from ordinary audio CDs, burning the corrected files on some fresh CDR and listening to them using a standard CD player. This avoids the need of any dedicated hardware and lets you test DRC on your favourite CD player. \subsection{Filter generation procedure} The creation of a correction filter for room acoustic compensation is quite a challenging task. A typical acoustic environment is a non minimum phase system, so in theory it cannot be inverted to get perfect compensation. Furthermore a typical HiFi system in a typical listening room isn't either a single linear system, but it is instead a different linear system for every different listening position available. Trying to get an almost perfect compensation for a given position usually leads to unacceptable results for positions which are even few millimeters apart from the corrected position. The generation of a filter that provides good compensation of magnitude and phase of the frequency response of the direct sound, good control of the magnitude of the frequency response of the stationary field and an acceptable sensitivity on the listening position, requires many steps. Here it is a brief summary of what DRC does: \begin{enumerate} \item Initial windowing and normalization of the input impulse response. \item Optional microphone compensation. \item Initial dip limiting to prevent numerical instabilities during homomorphic deconvolution. \item Decomposition into minimum phase and excess phase components using homomorphic deconvolution. \item Prefiltering of the minimum phase component with frequency dependent windowing. \item Frequency response dip limiting of the minimum phase component to prevent numerical instabilities during the inversion step. \item Prefiltering of the excess phase component with frequency dependent windowing. \item Normalization and convolution of the preprocessed minimum phase and excess phase components (optional starting from version 2.0.0). \item Impulse response inversion through least square techniques or fast deconvolution. \item Optional computation of a psychoacoustic target response based on the magnitude response envelope of the corrected impulse response. \item Frequency response peak limiting to prevent speaker and amplification overload. \item Ringing truncation with frequency dependent windowing to remove any unwanted excessive ringing caused by the inversion stage and the peak limiting stage. \item Postfiltering to remove uncorrectable (subsonic and ultrasonic) bands and to provide the final target frequency response. \item Optional generation of a minimum phase version of the correction filter. \item Final optional test convolution of the correction filter with the input impulse response. \end{enumerate} Almost each of these steps have configurable parameters and the optional capability to output intermediate results. Of course I'm not sure at all that this is the best procedure to get optimal correction filters. There is a lot of psychoacoustic involved in the generation of room acoustic correction filters, so probably the use of a more psychoacoustic oriented procedure would give even better results. Any suggestion with respect to this is appreciated. Within my HiFi system the application of the correction provides huge improvements. By the way my system no longer can be considered a normal HiFi system. It is actually much closer to a studio monitoring system placed in a heavily damped room. Furthermore there is also an high performance subwoofer, extending the response down into the infrasonic range, and everything has been tuned to provide the best results with the correction in place. For some example of the results achieved see appendix \ref{SampleResults}. \subsection{Frequency dependent windowing} \label{FrequencyDependentWindowing} The frequency dependent windowing is one of the most common operations within DRC. This type of windowing follow up directly from the fact that within a room the sensitivity of the room transfer function to the listening position is roughly dependent on the wavelength involved. This of course implies that the listening position sensitivity increase quite quickly with frequency. This dependence has the side effect that the room correction need to be reduced as the frequency increase, or, seen from the other side, as the wavelength decrease. For this reason DRC tries to apply a correction that is roughly proportional to the wavelength involved. This approach has also some psychoacoustic implications, because our auditory system is conceived to take into account the same exact room behaviour, and so its own behaviour follow somewhat similar rules. Within DRC the frequency dependent windowing is implemented with two different kind of procedures: band windowing and sliding lowpass linear time variant filtering. The first procedure simply filters the input signals into logarithmically spaced adjacent bands and applies different windows to them, then summing the resulting signals together to get the output windowed impulse response. The second procedure uses a time varying lowpass filter, with a cut-off frequency that decreases with the window length. The results are pretty similar, but usually the sliding lowpass procedure is preferred because it is less prone to numerical errors and allows for a bit more of flexibility. Both procedures follow the same basic rules in order to define the type of windowing that gets applied to the input signal. The basic parameters are the lower window, i.e. the window applied at the lower end of the frequency range involved, the upper window, i.e. the window applied at the upper end of the frequency range, and the window exponent, i.e. the exponent used to connect the lower window to the upper window with a parametric function that goes as the inverse of the frequency. For a description of the parametric function used see section \ref{MPWindowExponent}. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-Linear} \caption{\label{PrefilterLinear} Frequency dependent windowing for the normal.drc sample settings on the time-frequency plane. Linear scale. The X axis is time in milliseconds, the Y axis is frequency in Hz. The part that gets corrected is the one below the windowing curves.} \end{center} \end{figure} For example figure \ref{PrefilterLinear} show the typical set of prefiltering curves applied to the input impulse response by the normal.drc sample settings (see section \ref{SampleConfigurationFiles}). For this sample settings file the default setting for the window exponent, which is the WE parameter in the figure, is 1.0. The part of the input impulse response that is preserved, and so also corrected, is the one below the curves. The remaining part of the time-frequency plane is simply windowed out and ingored in the correction. Looking at this figure it becomes pretty clear that only a tiny fraction of the time-frequency plane gets corrected by DRC. This tiny fraction pretty much defines the physical limits where digital room correction is applicable. Above this limit the listening position sensitivity usually becomes so high that even a small displacement of the head from the optimal listening position causes unacceptable results with the appearance of strong audible artifacts. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-SemiLogY} \caption{\label{PrefilterSemilogY} Frequency dependent windowing for the normal.drc sample settings on the time-frequency plane. Logarithmic frequency scale. The X axis is time in milliseconds, the Y axis is frequency in Hz.} \end{center} \end{figure} By the way it should be also taken into account that our ear perceives this time-frequency plane on a logarithmic frequency scale. Looking at the same graph on a logarithmic frequency scale, as in figure \ref{PrefilterSemilogY}, it becomes clear that from our auditory system point of view a much bigger fraction of the time-frequency plane gets corrected. It becomes also clear that above 1-2 kHz only the direct sound gets corrected and that above that range room correction actually reduces to just minimalistic speaker correction. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-SemiLogX} \caption{\label{PrefilterSemilogX} Frequency dependent windowing for the normal.drc sample settings on the time-frequency plane. Logarithmic time and linear frequency scales. The X axis is time in milliseconds, the Y axis is frequency in Hz.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-LogLog} \caption{\label{PrefilterLogLog} Frequency dependent windowing for the normal.drc sample settings on the time-frequency plane. Logarithmic time and frequency scales. The X axis is time in milliseconds, the Y axis is frequency in Hz.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-Gabor} \caption{\label{Gabor} Frequency dependent windowing for the normal.drc sample settings on the time-frequency plane. Logarithmic time and frequency scale with Gabor limit superimposed. The X axis is time in milliseconds, the Y axis is frequency in Hz.} \end{center} \end{figure} While developing DRC I've read some informal notes on the Internet stating that on short time windows our perception of time should be considered on a logarithmic scale too. I'm not quite convinced that this assumption is actually true, but if such an assumption is correct our perception of the room correction would be as in figures \ref{PrefilterSemilogX} and \ref{PrefilterLogLog}. Even if this assumption is not true these graphs are pretty useful to make clearly visible the part of the time-frequency plane that gets corrected by DRC and becomes even more useful if also the Gabor limit is placed in the graph as in figure \ref{Gabor}. The Gabor limit is defined by the following simple inequality: \begin{displaymath} \Delta f \Delta t > \frac{1}{2} \end{displaymath} where $f$ is frequency and $t$ is time, and defines the limit of uncertainity in the time-frequency plane. This means for example that, looking at picture \ref{Gabor}, when the window exponent goes below about $0.5$ the frequency dependent windowing starts violating the Gabor inequality at least in some small frequency range. Within that range the room transfer function estimation performed by DRC becomes inaccurate and the room correction might be affected by appreciable errors in the evaluation of the room transfer function. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-BPComparison} \caption{\label{BPComparison} Comparison between the standard proportional windowing curve and the new one based on the bilinear transformation. Logarithmic time and frequency scale. The X axis is time in milliseconds, the Y axis is frequency in Hz.} \end{center} \end{figure} Starting with version 2.6.0 a prefiltering curve based on the bilinear transform has been introduced. This curve provides a better match with the typical resolution of the ear and also with the typical behaviour of the listening room. The windowing curve provides the same exact results as the previous windowing curve when the window exponent is set to 1.0, but provides a different behaviour when the window exponent is changed, as showed in figure \ref{BPComparison}. The closer approximation of the ear behaviour is clearly visible in figure \ref{BandwidthComparison}, where it is shown that using an appropriate configuration of the windowing parameters it is possible to get a close to perfect match with the ERB psychoacoustic scale (see curves labeled ERB and erb.drc, which overlap almost perfectly). \subsubsection{Pre-echo truncation} \label{Pre-echoTruncation} Starting from version 2.7.0 this step is implicitely disabled. Considering that excess phase inversion is performed simply by time reversal of the excess phase component, pre-echo is implicitely limited by the frequency dependent windowing performed on the excess phase. The description of this step and the code performing it has been retained because it could be used for experimental reasons, especially considering that the reequalization to flat performed in this step is time reversed with respect to that performed in the excess phase pre-processing. This meas that a minimum phase reequalization performed in the pre-echo truncation is equivalent to a maximum phase reequalization in the excess phase pre-processing, and the other way around. If enabled frequency dependent windowing is used to truncate the pre-echo caused by the inversion of the excess phase part of the impulse response. The truncation procedure is always the same but it is implicitely applied on the left side of the time-frequency plane instead of the right side, because inversion of the excess phase corresponds to a time reversal. A much shorter windowing is used because our ear is quite sensitive to pre-echo. Windowing out part of the impulse response of the excess phase component of the correction filter of course makes it no longer an all-pass filter, i.e. the excess phase part no longer has a flat magnitude response. To compensate for this problem the excess phase component magnitude response is equalized back to flat using, after inversion, a minimum phase filter. This of course causes some post-ringing. Even though this usually happens only on few narrow bands, it might be quite audible, and gets limited by the subsequent ringing truncation stage. \subsubsection{Ringing truncation stage} \label{RingingTruncationStage} Since version 2.5.0 a further frequency dependent windowing is applied directly to the filter after impulse response inversion and peak limiting. This is performed to remove any residual ringing caused by the previous steps, especially the dip and peak limiting steps, even though this implies some tradeoff on filter accuracy. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-Jail} \caption{\label{FDWJail} Frequency dependent windowing jail for the normal.drc sample settings on the time-frequency plane. Linear time scale and logarithmic frequency scale. The X axis is time in milliseconds, the Y axis is frequency in Hz.} \end{center} \end{figure} With this further step the filter impulse response gets enclosed in a sort of time-frequency jail defined by the excess phase windowing settings on the left side of the time-frequency plane and by the ringing truncation settings on the right side (see figure \ref{FDWJail}). Considering that this time-frequency bounds have also some psychoacoustic implications, with this time-frequency enclosure DRC should be able to truncate automatically any part of the correction that is probably going to cause audible artifacts. Following this lines DRC gains at least a bit of psychoacoustically based ``self tuning'' and should become more robust and less prone to artifacts. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-BWidthCmp} \caption{\label{BandwidthComparison} Resolution bandwidth, as a function of frequency, for the frequency dependent windowing and various standard smoothing procedures, including the Bark and ERB psychoacoustic scales. The X axis is frequency in kHz, the Y axis is frequency in Hz, both plotted on a logarithmic scale. The windowing parameters of the normal.drc and erb.drc sample settings files have been used to plot the DRC resolution curves.} \end{center} \end{figure} Applying the Gabor inequality to the window length between the two curves of pre-echo and ringing truncation it is pretty easy to get an equivalent frequency resolution, as a function of center frequency, of the frequency dependent windowing procedure. This resolution could be compared, as in figure \ref{BandwidthComparison}, to some standard smoothing procedures widely used within many audio applications, like fractional octave smoothing and the classical Bark and ERB psychoacoustic scales. From figure \ref{BandwidthComparison} it is pretty clear that the correction resolution used by DRC is well above that of any of the standard smoothing procedures, at least with the normal.drc sample settings file (see section \ref{SampleConfigurationFiles}). This means that the correction should provide a perceived frequency response that is really close to the configured target frequency response. The ``erb.drc'' resolution plot show the approximation of the ERB scale provided by the ``erb.drc'' sample settings file (see section \ref{SampleConfigurationFiles}. The approximation has been created assuming: \begin{displaymath} \Delta f \Delta t = 2 \end{displaymath} instead of the usual Gabor inequality (see figure \ref{Gabor}), i.e. assuming that the frequency dependent windowing with the settings used has a resolution that is about four times above the Gabor limit. This is a rough estimate of the true resolution achieved by the DRC procedure in this situation. This estimation has been derived considering the compound effect of the various overlapped windows applied at various stages of the filter generation procedure. \subsection{Psychoacoustic target computation} \label{PsychoacousticTargetComputation} Starting from version 3.0.0 an optional stage, used to compute a target frequency response based on the psychoacoustic perception of the corrected frequency response, has been introduced. The target response is based on the computation of the magnitude response envelope of the corrected impulse response, which is an extension of the spectral envelope concept. This is performed before the application of the usual target response, so that the standard target response is not compensated back by this stage. The spectral envelope is a concept which has been introduced in the field of speech synthesis and analysis and is defined simply as a smooth curve connecting or somewhat following the peaks of the signal spectrum. There are strong arguments and experimental evidence supporting this approach and the idea that our ear uses the spectral envelope for the recognition of sounds. The spectral envelope, for example, allow our ear to understand speech under many different conditions, whether it is voiced, whispered or generated by other means. These different conditions generate completely different spectrums but usually pretty similar spectral envelopes. The spectral envelope also easily explains why our ear is more sensitive to peak in the magnitude response and less sensitive to dips. A curve based on the peaks of the magnitude response is by definition little or not affected at all by dips in the frequency response. In the speech recognition field many procedures have been developed to compute the spectral envelope. Some of them are based on Linear Predictive Coding (LPC), the Discrete Cepstrum, the so called ``True Envelope'' and finally the Minimum Variance Distortionless Response (MVDR). Most of these methods are optimized for speed, noise resilience and to provide good results in the voice spectrum range sampled at low sample rates, so they are not really suited for HiFi usage. Within DRC a different procedure has been developed. This is a variation of the usual fractional octave smoothing procedure, using the parametric H\"older mean instead of the usual simple averaging. Furthermore the smoothing has been extended to provide the Bark and ERB scales resolution when applicable. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-SpectralEnvelope} \caption{\label{SpectralEnvelope} Example of a magnitude response envelope. The unsmoothed magnitude response of a typical room, corrected with a flat target, is plotted. Superimposed there is the usual smoothing, computed on the ERB scale, showing an essentially flat magnitude response, as expected. The magnitude response envelope, computed on the ERB scale too using standard parameters, show a rising slope which is in good agreement with the inverse of one of the target responses suggested in the literature.} \end{center} \end{figure} For the tuning of the parameters used in the magnitude response envelope computation some typical real world room magnitude responses have been taken. The computation parameters have been set so that the resulting magnitude response envelope provides a target response as close as possible to the inverse of the usual target responses suggested in the literature. An example is reported in picture \ref{SpectralEnvelope}. The same parameters have been tested also in some not so common room to check that they were still providing the expected results. Of course, considering that now the basic target response is provided by the inverse of the magnitude response envelope, the usual target responses are no longer needed, apart from subsonic or ultrasonic filtering, and should be set to flat. For this reason the flat response is now the default target for all standard configuration files. The standard target response stage should be used only to adjust the response to taste, but, unlike previous versions, for a neutral reproduction a flat response should be used. From the subjective point of view a system equalized to the inverse of the magnitude response envelope usually sound really neutral. Even though most of the times the magnitude response envelope response is different among the various channels, resulting in an obvious channel misalignement if evaluated with the standard smoothing procedures, imaging usually improves, becoming more stable and focused. This appear to confirm that the estimation performed by the magnitude response envelope has to be close to the subjective perception of the magnitude response. % Misura della risposta all'impulso \subsection{Impulse response measurement} \label{ImpulseResponseMeasurement} Starting from version 2.4.1 two simple command lines tools, glsweep (Generate Log Sweep) and lsconv (Log Sweep Convolution), are available to perform accurate time aligned impulse response measurements. These tools are based on the log sweep method for impulse response measurement, which is one of the most accurate, especially for acoustic measurements. This method is based on a special signal, which is a logarithmic sinusoidal sweep, that need to be reproduced through the system under test, and an inverse filter, which, when convolved with the measured log sweep, gives back the impulse response of the system. The steps needed to get the impulse response are the following: \begin{enumerate} \item Generate the log sweep and inverse filter using glsweep, optionally converting the sweep to a suitable format. \item Play the log sweep through your system using a soundcard while recording the speaker output using a (hopefully good) microphone and any recording program. \item Convolve the recorded log sweep with the inverse filter using lsconv to get the final impulse response. \end{enumerate} If full duplex is supported by the soundcard, recording may be performed using the same soundcard used for playing. Using two different soundcards or a CD Player for reproduction and a soundcard for recording usually provides worse results unless they are accurately time synchronized. The lsconv tool allows also for the use of a secondary reference channel to correct for the soundcard frequency response and for any time misalignment caused by the soundcard itself, the soundcard drivers or the play and recording programs. This soundcard compensation of course works if the reference channel has the same behaviour of the measuring channel. The typical use of this feature would be the use of one channel of a stereo or multichannel soundcard to measure the system and another one used in a loopback configuration to get the reference channel needed to correct the soundcard itself. With this configuration even with cheap soundcards it is pretty easy to get a $ \pm 0.1 $ dB frequency response over the audio frequency range with near to perfect time alignment and phase response. Considering that the log sweep method ensure by itself a strong noise rejection (90 dB of S/N ratio is easily achievable even in not so quiet environments) and a strong rejection to artifacts caused by the system non linear distortions, with this method the final measurements usually have true state of the art accuracy. Finally an important warning: playing the log sweep signal at an excessive level can easily damage your speakers, especially the tweeters. So be really careful when playing such a signal through your equipment. No responsibility is taken for any damage to your equipment, everything is at your own risk. \subsubsection{The glsweep program} When executed without parameters the glsweep program gives the following output: \begin{quote} {\scriptsize \begin{verbatim} GLSweep 1.0.2: log sweep and inverse filter generation. Copyright (C) 2002-2005 Denis Sbragion Compiled with single precision arithmetic. This program may be freely redistributed under the terms of the GNU GPL and is provided to you as is, without any warranty of any kind. Please read the file "COPYING" for details. Usage: glsweep rate amplitude hzstart hzend duration silence leadin leadout sweepfile inversefile Parameters: rate: reference sample rate amplitude: sweep amplitude hzstart: sweep start frequency hzend: sweep end frequency duration: sweep duration in seconds silence: leading and trailing silence duration in seconds leadin: leading window length as a fraction of duration leadout: trailing window length as a fraction of duration sweepfile: sweep file name inversefile: inverse sweep file name Example: glsweep 44100 0.5 10 21000 45 2 0.05 0.005 sweep.pcm inverse.pcm \end{verbatim} } \end{quote} The program output contains some brief explanation of the generation parameters and some sample options. The longer the log sweep used the stronger the noise rejection of the measure. A 45 seconds log sweep usually gives more than 90 dB of signal to noise ratio in the final impulse response even when used in somewhat noisy environments, for example one where the computer used to do the measure is in the same room of the measured system, producing all of its fan noise. The output format is the usual raw file with 32 bit IEEE floating point samples. If you need to convert the sweep generated using the example above to a 16 bit mono WAV file you can use SoX with a command line like this one: \begin{quote} {\scriptsize \begin{verbatim} sox -t f32 -r 44100 -c 1 sweep.pcm -t wav -c 1 sweep.wav \end{verbatim} } \end{quote} SoX, can be downloaded at: \begin{quote} \url{http://sox.sourceforge.net/} \end{quote} If you want to create a stereo WAV file to get also the reference channel you can use something like: \begin{quote} {\scriptsize \begin{verbatim} sox -t f32 -r 44100 -c 1 sweep.pcm -t wav -c 2 sweep.wav \end{verbatim} } \end{quote} The inverse filter doesn't need to be converted to a WAV file because lsconv is already able to read it as is. If you need to convert a recorded sweep stored in a wav file back to a raw 32 bit floating point format use this command: \begin{quote} {\scriptsize \begin{verbatim} sox recorded.wav -t f32 recorded.pcm \end{verbatim} } \end{quote} If you have a stereo WAV file with both the measurement channel and the reference channel you can extract them into two files using: \begin{quote} {\scriptsize \begin{verbatim} sox recorded.wav -t f32 -c 1 recorded.pcm mixer -l sox recorded.wav -t f32 -c 1 reference.pcm mixer -r \end{verbatim} } \end{quote} provided that the recorded channel is the left one (``mixer -l'' parameter) and the reference channel is the right one (``mixer -r'' parameter). \subsubsection{The lsconv program} When executed without parameters the lsconv program gives the following output: \begin{quote} {\scriptsize \begin{verbatim} LSConv 1.0.3: log sweep and inverse filter convolution. Copyright (C) 2002-2005 Denis Sbragion Compiled with single precision arithmetic. This program may be freely redistributed under the terms of the GNU GPL and is provided to you as is, without any warranty of any kind. Please read the file "COPYING" for details. Usage: LSConv sweepfile inversefile outfile [refsweep mingain [dlstart]] Parameters: sweepfile: sweep file name inversefile: inverse sweep file name outfile: output impulse response file refsweep: reference channel sweep file name mingain: min gain for reference channel inversion dlstart: dip limiting start for reference channel inversion Example: lsconv sweep.pcm inverse.pcm impulse.pcm refchannel.pcm 0.1 0.8 \end{verbatim} } \end{quote} All files must be in the usual raw 32 bit floating point format. To get the impulse response without the use of a reference channel just use something like: \begin{quote} {\scriptsize \begin{verbatim} lsconv recorded.pcm inverse.pcm impulse.pcm \end{verbatim} } \end{quote} Where ``recorded.pcm'' is the recorded sweep, ``inverse.pcm'' is the inverse filter generated by glsweep and ``impulse.pcm'' is the output impulse response ready to be fed to DRC. If you also want to use the reference channel use something like: \begin{quote} {\scriptsize \begin{verbatim} lsconv recorded.pcm inverse.pcm impulse.pcm reference.pcm 0.1 \end{verbatim} } \end{quote} The ``0.1'' value is the minimum allowed gain for the reference channel inversion. $0.1$ is the same as -20 dB, i.e. no more then 20 dB of the reference channel frequency response will be corrected. This is needed also to prevent numerical instabilities caused by the strong cut off provided by the soundcard DAC and ADC brick wall filters. When used with the reference channel the main spike of the impulse response is always at exactly the same length of the log sweep used, provided that the two soundcard channels are perfectly synchronized. Of course this is usually true for all soundcards. For example if a 10 seconds sweep is used the main spike will be exactly at 10 seconds from the beginning of the output impulse response, i.e. at sample 441000 if a 44.1 kHz sample rate is used. If the main spike is at a different position it means that there's some delay in the measurement channel, usually caused by the time the sound takes to travel from the speaker to the microphone. If this delay is different for different channels it means that there's a time misalignment between channels that needs to be corrected. Up to a limited amount, and using some small tricks, DRC is already able to compensate for interchannel delays (see section \ref{InterchannelTimeAlignment}). Some future DRC release will include better support for interchannel time alignment. \subsubsection{Sample automated script file} Under the ``source/contrib/Measure'' directory of DRC there's a sample Linux shell script, called ``measure'', that uses glsweep, lsconv, SoX and standard ALSA play and recording tools to automate the time aligned measurement procedure using a reference channel. This sample script can be used only under Linux and it is just a quick hack to allow expert users to automate the whole procedure. Use it at your own risk. Furthermore this script has been developed with an old version of SoX (12.17.7) so it might need some changes to work with more recent versions. It also needs any related tools ready to be executed from the working directory, else it doesn't work. When executed without parameters the script gives the following output: \begin{quote} {\scriptsize \begin{verbatim} Automatic measuring script. Copyright (C) 2002-2005 Denis Sbragion This program may be freely redistributed under the terms of the GNU GPL and is provided to you as is, without any warranty of any kind. Please read the file COPYING for details. Usage: measure bits rate startf endf lslen lssil indev outdev impfile [sweepfile] bits: measuring bits (16 or 24) rate: sample rate startf: sweep start frequency in Hz endf: sweep end frequency in Hz lslen: log sweep length in seconds lssil: log sweep silence length in seconds indev: ALSA input device outdev: ALSA output device impfile: impulse response output file sweepfile: optional wav file name for the recorded sweep example: measure 16 44100 5 21000 45 2 plughw plughw impulse.pcm \end{verbatim} } \end{quote} This script assumes that the measuring channel is on the left channel and that the reference channel is the right one. To use it just take a look at the sample command line provided above. You have to provide proper ALSA input and output devices, but ``plughw'' usually works with most soundcards. Using 24 bits of resolution to measure an impulse response is usually just a waste of resources. In most rooms getting a recorded sweep with more than 60 dB of S/N ratio is close to impossible, so 16 bits of resolution are already plain overkill. On the other hand, thanks to the strong noise rejection provided by the log sweep method, a sweep S/N ratio of 60 dB is already high enough to get more than 90 dB of S/N ratio in the recovered impulse response, at least with a 45 s sweep running at a 44.1 kHz sample rate. The impulse response is what DRC works on, so it is the impulse response that needs an high S/N ratio, not the sweep. If you really want a better impulse response S/N ratio, or if you measure in a noisy environment, increase the sweep length instead of using 24 bits of resolution. A longer sweep will improve the S/N ratio of the impulse response, increasing the resolution instead will provide no benefit at all. Chris Birkinshaw created a modified version of the measure script which adds Jack support. The script is named ``measurejack'' and you can find it under the ``source/contrib/MeasureJack'' directory of the standard distribution. For informations about Jack take a look at: \begin{quote} \url{http://jackaudio.org/} \end{quote} \subsubsection{Beware cheap, resampling, soundcards} Most cheap game oriented soundcards often include a sample rate converter in their design, so that input streams running at different sample rates can be played together by resampling them at the maximum sample rate supported by the soundcard DAC. Usually this is 48 kHz as defined by the AC97 standard. These sample rate converters often are of abysmal quality, causing all sort of aliasing artifacts. Most deconvolution based impulse response measurement methods, including the log sweep method, are quite robust and noise insensitive, but cause all sorts of artifacts when non harmonic but signal related distortion is introduced, even at quite low levels. The aliasing artifacts introduced by low quality sample rate converters are exactly of this kind and are one of the most common cause of poor quality impulse response measurements and consequently of correction artifacts. \subsubsection{How to work around your cheap, resampling, soundcard} Despite this, most of the times good measurements are possible even out of cheap soundcards if the maximum sample rate supported by the DAC is used, usually 48 kHz, so that the soundcard internal sample rate converter isn't used at all. You can change the impulse response sample rate after the measurement using high quality software sample rate conversion algorithms (see section \ref{SampleRateConversion}), thus preserving the impulse response quality. To check the quality of the impulse response measurement perform a loopback measurement, without using a reference channel else any measurement problem will be washed out by the reference channel compensation. The impulse response you get must be a single clean spike much similar to that of a CD Player (see for example the upper graph of picture \ref{BaselineImpulseResponseFullRange}, labeled ``Dirac delta''). A bit of ringing before and/or after the main spike is normal, but anything else is just an artifact. Only when you are sure that the measurement chain is working as expected open the loopback and do the real measurement, eventually adding also a reference channel to compensate for any remaining soundcard anomaly. \subsection{Sample rate conversion} \label{SampleRateConversion} If you have the impulse response sampled at a different rate than the one needed for the final filter, you need to convert the sample rate before creating or applying the filters. For example you might have a 48 kHz impulse response but you may need to filter standard CD output at 44.1 kHz. In this situation you can either convert the impulse response to 44.1 kHz before feeding it to DRC or you can convert the resulting filters to 44.1 kHz after DRC has created them. I generally prefer the first procedure, which leads to exact filter lengths in the DRC final windowing stage, but in both cases you need a good quality sample rate converter, which uses, for example, band limited interpolation. A reasonable choice, free both under Linux and Win32, is SoX, which may be downloaded at: \begin{quote} \url{http://sox.sourceforge.net/} \end{quote} Recent versions of SoX include some top quality sample rate conversion routines. SoX also provides a lot of other features for sound files manipulation. Another free good sample rate converter comes from the shibatch audio tools suite. This sample rate converter provides a quality which is adequate for the task of converting the impulse response file before feeding it to DRC. You can find the shibatch audio tools at: \begin{quote} \url{http://shibatch.sourceforge.net/} \end{quote} \subsection{Correction tuning} \label{CorrectionTuning} Proper tuning of the correction filter generation procedure easily provides a substantial improvement over the standard sample configuration files provided along with DRC (see section \ref{SampleConfigurationFiles}). To properly tune the filters to closely match your room behaviour there are many different issues that should be taken into account. \subsubsection{Preventing pre-echo artifacts} \label{AvoidPreEchoArtifacts} One of the main problems in digital room correction are pre-echo artifacts that arise when compensation accuracy is pushed above a certain threshold. This pre-echo artifacts usually occur on narrow bands and are easily audible as a sort of ringing or garble before transients or sharp attacks. In order to avoid them there are basicly two options: \begin{itemize} \item Reduce the correction on critical frequency regions where pre-echo artifacts may arise. \item Use a minimum phase approach to avoid pre-echoes. This way you get increased ringing after the main spike instead of pre-echo, but this is usually masked both by our ear temporal masking and by the reverberant nature of common listening rooms, so it is much less audible, if audible at all. \end{itemize} DRC uses both options in different steps of the correction procedure. So in order to avoid pre-echo artifacts you basically have to: \begin{itemize} \item Reduce the amount of correction applied to the excess phase component by reducing the size of the frequency dependent window applied. With the standard configuration files this is usually everything that need to be done, because all the other procedures are already configured to avoid pre-echo problems. \item Use a long enough FFT where circular convolution is involved (basicly homomorphic deconvolution and pre-echo truncation inversion), because circular artifacts may easily become pre-echo. \item Use the single side sliding lowpass prefiltering procedure; this is just because of small numerical errors in band windowing that causes small amounts of pre-echo on band edges. \item Use the minimum phase versions for some of the accompanying procedures (peak and dip limiting for example) \item Use the pre-echo truncation fast deconvolution for the inversion procedure, with appropriate pre-echo truncation parameters. By the way, if the excess phase component windowing parameters are already set appropriately, this should not be needed. \end{itemize} The sample configuration files supplied are a good example of all these options combined together. In normal situations you can use them as they are changing only EPLowerWindow, EPWindowExponent, MPLowerWindow and MPWindowExponent to fit your needs. \subsubsection{Preventing clipping} \label{PreventingClipping} One of the problems of real time correction is the prevention of DAC clipping caused by the filter intrinsic amplification. First of all the normalization factor to be used (see sections \ref{PSNormFactor} and \ref{MCNormFactor}) depends on the convolver used. Some convolvers want the filter normalized to the 16 bit range, i.e. 32768, most others want a standard normalization, i.e. normalization to $\pm 1.0$. For example BruteFIR needs a filter normalized to 1.0 to get 0 dB amplification between input and output. All the normalization steps used within DRC, included those needed to output the final filter (see sections \ref{PSNormType} and \ref{MCNormType}), accept four types of normalization: \begin{itemize} \item S, i.e. sum normalization, also called $L_1$ norm \item E, i.e. euclidean normalization, also called $L_2$ norm \item M, i.e. Max normalization, also called $L_\infty$ norm \item P, i.e. Peak normalization, i.e. normalization to the highest amplitude response peak \end{itemize} For a detailed description of the four types of normalization see section \ref{BCNormType}. The S normalization guarantees against overflows in the output stream, i.e. it guarantees that if any input sample is never greater than X than any output sample is never greater than X multiplied by the normalization factor. This means also that if the normalization factor is 1 and the input sample is never greater than 32767 (i.e. the input is a 16 bit stream) the output is never greater than 32767, i.e. a 16 bit DAC on output will never clip or overflow. Anyway, using common musical signals, and depending on the filter frequency response, the use of the S normalization might lead to filters with a global gain substantially lower than 1 (0 dB), i.e. filters with a typical output level which is lower, most of the times much lower, than the input level. With such low levels part of the resolution of the DAC gets lost. With normal musical signals it is usually safe to use a filter with an S normalization factor greater than 1, because, considering the typical frequency response of a room, and the corresponding reversed frequency response of the filter, overflows would occur in frequency ranges where typically there is not enough musical signal to cause it. A good extimation of an adequate normalization factor might be provided by the P normalization, which rescales the filter so that the highest peak in the magnitude response corresponds to a 0 dB gain. Contrary to intuition this doesn't completely ensure that there would never be clipping on output, but for most common musical signals it usually provide a safe extimation without introducing excessive attenuation. If you use BruteFIR one possible approach is to use 1 for the PSNormFactor and S for PSNormType and then use the rescaling and monitoring features of BruteFIR to boost the gain up to few dB below overflow with typical musical signal. You might try using a 0 dB white noise source as a sort of worst case situation. Be careful setting the basic filter gain. I found that many recent musical recordings, especially compressed and rescaled pop music productions, cause output levels that are just 1 or 2 dB below the white noise worst case scenario. The degradation in the sound quality caused by DAC clipping is typically much more audible than the degradation you get loosing a single bit or less of your DAC resolution, especially if you use 16 bit DACs along with dithering or 24 bits DACs. If you're unable to perform a test using 0 dB white noise as the input signal and for some reason you don't want to rely on the estimation performed by the P normalization, a simple rule of thumb is to use the E normalization with a normalization factor which is a couple of dB lower than the maximum gain allowed during peak limiting. With the standard configuration files, where the maximum allowed gain is never greater than about 6 dB, this means using a normalization factor around $0.3 - 0.4$ with convolvers which use 1.0 as the 0 dB reference level like BruteFIR, or using something like 10000 - 13000 with convolvers which use 32768 as the 0 dB reference level. The default configuration files all use the E normalization with a normalization factor set to 1, leaving the task of scaling the filter gain to avoid clipping to the convolver. With the default configuration files you should set the convolver gain to something below $-6 dB$, which is the default maximum gain allowed by the peak limiting procedure. \subsubsection{Some notes about loudspeaker placement} As most audio practitioneers already know, in a basic stereo loudspeaker configuration it is important that the distance between the loudspeakers and the listening position is exactly the same for both loudspeakers, and also not too different from the distance between the two loudspeakers themselves (the classical equilateral triangle placement). If this rule isn't satisfied usually the stereo image become distorted and confused. With digital room correction enabled this rule becomes of paramount importance. DRC doesn't automatically compensate for delays caused by loudspeaker misplacement and having the two channels with near to perfect direct sound, both in phase and magnitude, makes any difference in the arrival time immediately and clearly audible, with a nasty phasey sound and a blurred stereo image. Less than 10 cm are enough to cause clearly audible problems, so take your time to measure the distance from both loudspeakers and the listening position before doing any measure, and also do your measures by placing the microphone exactly at the listening position. Furthermore, with digital room correction it is worth to experiment with unusual speaker placements. Reflections from nearby walls are more difficult to correct when they are away from the main spike, so placing the speakers near to the walls, or may be even in the corners, might sometime give better results with DRC, provided that you place some absorbing material near the speakers to remove early reflections in the high frequency range, where DRC is able to correct only the direct sound. This type of placement is exactly the opposite of what is usually done if you don't use digital room correction, where it is usually better to try to put loudspeakers away from the walls to avoid early reflections, that cause major problems to the sound reproduction and almost always boomy bass. Anyway, remember that there is no ready to use recipe to find the best speaker placement, even with DRC in use, so a bit of experimenting is always needed. \subsubsection{Some notes about channel balance} DRC doesn't compensate for channel level imbalance, so this should be done manually after correction by changing a little the filters level until a perfect balance is achieved. This is of course better achieved using an SPL meter with pink noise and proper weighting. Anyway after correction the two channels start having a frequency response that is pretty much the same, so achieving perfect balance becomes pretty easy even by ear. Just use a mono male, or, better, female voice, and adjust the filters level until the voice comes exactly from the center of both loudspeakers. To achieve a good balance you might also use the level hints provided by DRC at the end of the correction procedure, provided that the measured impulse responses have levels that are directly related to the original levels of the channels, i.e. these levels haven't been changed by the measuring procedure itself. \subsubsection{Interchannel time alignment} \label{InterchannelTimeAlignment} First of all the current DRC release is able to compensate for interchannel misalignment of only few samples, no more than $ \pm 8 $ with the default configuration files. Furthermore accurate time aligned measurements must be supplied, using either the glsweep and lsconv tools with a reference channel or some other tool providing the same degree of accuracy. To get this limited time alignment you have to execute the following steps: \begin{enumerate} \item Execute DRC on one channel as usual. At the beginning of the DRC output on screen you will see a line like this one: \begin{quote} \begin{verbatim} Impulse center found at sample 1367280. \end{verbatim} \end{quote} Take note of the impulse center value. \item After DRC has finished prepare the configuration files for the other channels as usual but change the BCImpulseCenterMode parameter to M and the BCImpulseCenter parameter from 0 to the value of the impulse center noted before for the first channel. This way DRC will use the value of the impulse center of the first channel as a reference for the other channels and will compensate for any misalignment with respect to the first channel. If channels are misaligned more than few samples this will cause errors in the correction filters, usually causing a rising frequency response, and so a bright sound. \end{enumerate} \subsubsection{How to tune the filters for your audio system} \label{HowToTuneFilters} A proper tuning of the filters for your audio system and your listening room easily provides a substantial improvement over the standard configuration files. The best way to do this is to use the correction simulation provided by DRC and to check the results using the Octave scripts supplied with the documentation (see section \ref{SampleResults}), but if you have little experience with measurements interpretation you can also try to tune the correction by simple listening to the results, even though it isn't an easy task. One of the most common mistakes performed in the tuning procedure is the use of an excessive correction, which initially gives the impression of a good result, but cause also the appearance of subtle correction artifacts that becomes audible only with some specific musical tracks. These artifacts often have a peculiar resonant behaviour so they become audible only when they get excited by specific signals. To learn how to recognize them try using the ''insane.drc'' sample configuration file, which applies an overly excessive amount of correction, causing clearly audible artifacts on all but the most damped rooms. The best procedure to use is to start from the minimal amount of correction, like that provided by the minimal.drc or erb.drc correction settings. If your impulse response measurements are of good quality these minimalistic correction settings should already provide a substantial improvement over the uncorrected system, without any perceivable artifact. If this doesn't happen it's better to first double check the measurements performed before fiddling with the correction parameters. Remember that measurements problems are the most common cause of unsatisfactory correction results. After this first test you can slowly switch to stronger correction settings using the soft.drc, normal.drc, strong.drc and extreme.drc settings, always listening to the results after each step, if possible using quick switching between the filters. When correction artifacts start to arise, which usually happens between the normal.drc settings and the extreme.drc settings, it's time to stop and to start playing with some specific correction parameters. The first parameters to modify are those that define the windowing correction curve applied to the signal, i.e MPWindowExponent, EPWindowExponent, RTWindowExponent, slowly reducing them to 0.95, 0.9, 0.85 and so on, down to about 0.7, thus reducing the correction in the critical mid and mid-bass range. These are really sensitive parameters, so changing them by as little as 0.01 easily cause an audible difference, especially when you are close to the boundary where correction artifacts start to appear. When the artifacts disappear you can start increasing the windows applied to the bass range, slowly increasing, by about a 5\% at a time, the MPLowerWindow, EPLowerWindow, RTLowerWindow parameters, until artifacts start to appear again. After that you can decrease again the window exponent parameters until artifacts disappear again, and so on. This procedure may be repeated until there's no further improvement or the parameters reach an excessive value, i.e below about 0.6 for the window exponents, above 1 second for the minimum phase and ringing truncation windowing parameters (MPLowerWindow, RTLowerWindow) and above 100 ms for the excess phase windowing parameter (EPLowerWindow). Remember also to set the pre-echo truncation parameters (ISPELowerWindow, ISPEUpperWindow) according to the excess phase windowing parameters (see sections \ref{ISPELowerWindow} and \ref{ISPEUpperWindow}). Of course the tuning procedure has to be carefully adapted to your specific room, so, after a good tuning has been reached following the basic procedure, you can further try playing a little with the available parameters, applying even different values to each of them, proceeding one at a time to avoid confusion. By the way, be careful, because after the initial tuning the differences between the filters will start to be quite subtle, most of the times will be barely audible, and quick switching between the filters, possibly even under blind conditions, will become almost mandatory to really understand what's happening and which filter is better or at least audibly different. \section{Program compilation and execution} DRC can be compiled either under Win32 or Linux, but because of its simplicity it will probably work under most operating systems with a decent C++ compiler with support for the standard template library (STL). The Win32 executable (drc.exe) is provided precompiled with the standard DRC distribution under the sample directory, where there are also the executables for the impulse response measuring tools (glsweep.exe and lsconv.exe). A Makefile is provided for Linux and other Unixes, but it has been tested only under Fedora Core 11. To build the program under Linux usually what you have to do is just type ``make'' in the source directory of DRC, where the makefile resides. A Code::Blocks workspace is also available for use both under Win32 and Linux. Code::Blocks can be downloaded at: \begin{quote} \url{http://www.codeblocks.org/} \end{quote} The file drc.h contains a configurable define (UseDouble) which can be set to use double or float as the data type used for all internal computations. Despite some microscopic differences in the final output, I have never found any real advantage using doubles as the internal basic type. During the testing for the 3.1.0 release I have performed some tests to check the signal to noise ratio of the output filters. Despite the amount of processing performed and the fact that little effort has been placed into keeping the maximum accuracy throughout the processing, even using single precision arithmetic the signal to noise ratio of the final filter resulted to be greater than 140 dB in the worst case. This is more than 20 dB better than the signal to noise ratio provided by the best DACs available in the world. Considering these results the supplied Win32 executable is compiled for single precision. If you want to switch to the double precision you have to recompile it yourself. Of course using the double data type makes DRC a bit slower and, most important, much more memory intensive. Starting from version 2.4.0 DRC is able to use the Takuya Ooura and GNU Scientific Library FFT routines, which are included in the distributed package. The inclusion of these routines is controlled by the UseGSLFft and UseOouraFft defines in drc.h. These routines are about 10 times faster than the standard routines used by DRC, but to use them with the STL complex data type a clumsy hack has been used, and it is not guaranteed that this hack will work with all the STL implementations available. If it causes any problem simply comment out the UseGSLFft and UseOouraFft defines in drc.h and recompile the program. This will force DRC to use the older, slower but STL compliant FFT routines. The accuracy of the different FFT routines is pretty much the same. The Ooura routines work only with powers of two lengths, so they are used only with power of two lengths computations. Ooura FFT routines are somewhat faster than the GSL routines but are also a little bit less accurate. The default configuration uses only the GSL FFT routines, providing the best compromise between speed and accuracy. The Ooura FFT routines become useful when DRC is compiled for double precision arithmetic. Most text files supplied with the standard distribution use Unix line termination (LF instead of CR/LF). Be aware of this when opening files under Win32 systems. WordPad is able to open LF terminated text files, NotePad isn't. Finally an important note, especially for Win32 users. DRC is a console program, it has no graphical interface. All program execution parameters must reside in a plain ASCII text file which is supplied as an argument on the program command line. In order to execute the program you have to open a command prompt (or DOS Prompt or whatever is named a console in your version of Windows) and type something like: \begin{quote} \begin{verbatim} drc test.drc \end{verbatim} \end{quote} followed by a carriage return (enter or return key). Test.drc should be the text file already prepared with all the parameters needed to run DRC. Under Linux of course you have to use a console program (the Linux console, a terminal emulator like XTerm or something like this if you are using XWindows). The DRC executable must be in the system path or in the directory where you execute. \subsection{Command line parameters replacing} Starting from version 2.6.2 all the parameters available in the configuration file may be replaced by an equivalent parameter on the command line. For example if you want just to change the input and output filter files of the normal.drc sample configuration file you may use a command like this: \begin{quote} \begin{verbatim} drc --BCInFile=myfile.pcm --PSOutFile=myfilter.pcm normal.drc \end{verbatim} \end{quote} The parameter parsing procedure supports also quoting of filenames with spaces and setting of strings to empty values, which is the same as commenting a parameter in the configuration file. For example to use some filename with spaces, to disable the output of the test convolution file, to change the maximum allowed gain, all in a custom configuration file with spaces in its name, you could use a command line like this: \begin{quote} \begin{verbatim} drc --BCInFile="my file.pcm" --PSOutFile="my filter.pcm" --TCOutFile="" --PLMaxGain=3.5 "my custom config.drc" \end{verbatim} \end{quote} Along with all the default configuration parameters there is also a special ``--help'' parameter that show the full list of all the available parameters with the associated parameter type. The list of the parameters is really long, so some pager is needed to see them all. \subsection{Sample configuration files} \label{SampleConfigurationFiles} DRC has started as an experimental program and because of this it has a lot of tunable parameters, actually more than 150. Only few of them are really important for the final filter correction quality. Most of them are used just to take a look at intermediate results and check that everything is working as expected. DRC flexibility might of course be used also to deal with complex or unusual situations or to experiment with weird configurations. Along with the DRC distribution six main sample configuration files are provided: minimal-XX.X.drc, soft-XX.X.drc, normal-XX.X.drc, strong-XX.X.drc, extreme-XX.X.drc, insane-XX.X.drc. The ''XX.X' in the file name stands for the sample rate in kHz which the file is configured for. For example ''normal-44.1.drc'' is the normal configuration file for the 44.1 kHz sample rate. Considering that the only difference between the files is the base sample rate they are configured for, in the rest of this document all files are named omitting the sample rate part. The sample configuration files provide most parameters set to reasonable defaults, with stronger correction, but also worse listening position sensitivity, going from the minimal.drc settings to the extreme.drc settings. In the same directory of the configuration file there is also a sample impulse response (rs.pcm, this is the impulse response of the right channel of my previous HiFi system, in 32 bit IEEE raw format) usable with the sample configuration files to see just what happens when DRC is run. The insane correction settings are not meant for normal use but are used just to provide an example of excessive correction that is going for sure to cause audible correction artifacts. Using these settings file you can easily check how correction artifacts actually sound like, thus learning to identify them within normal filters while you are tuning them for your audio system (see section \ref{HowToTuneFilters}). Another interesting sample configuration is the one provided by the ``erb.drc'' file. This file provides an accurate approximation of the ERB psychoacoustic scale (see figure \ref{BandwidthComparison}). It is important to notice that basicly the correction isn't much stronger than the ``minimal.drc'' sample configuration, but being approximately tuned to our ear psychoacoustic resolution it is probably going to provide a good perceived correction accuracy with minimal listening position sensitivity, and so it is well suited for multiple listeners situations, like home theater applications. Starting form version 2.7.0 all sample configuration files are available for 44.1 kHz, 48 kHz, 88.2 kHz, 96 kHz sample rates. By the way you should be careful with sample rates above 44.1 kHz because most of this sample files have been simply derived from the 44.1 kHz version without testing them in real life situations. The sample configuration files for the higher sample rates aren't in the sample directory. To avoid placing a lot of similar files in the same directory the files for the higher sample rates are placed in the ''src/config'' directory. Remember also that all the sample correction files output the correction filter (rps.pcm) in 32 bit floating point format normalized to 1.0, which is the format suited for use with BruteFIR. Most sound editors expect 16 bits integer files normalized to 32768, so the file above might look either empty or completely clipped when opened with a sound editor without using the appropriate options. \subsubsection{Target magnitude response} \label{TargetMagnitudeResponse} Starting from version 3.0.0 the basic target magnitude response is automatically generated by DRC using a specific procedure based on some documented psychoacoustic assumptions. See section \ref{PsychoacousticTargetComputation} for the details. Because of this there should be no need to define a specific target curve and a flat target, with just some limiting for subsonic and ultrasonic frequencies, should be used instead. This is accomplished by using the pa-XX.X.txt target, which is now the default for all standard configuration files and is just a variation of the previous flat target adjusted to better work with the ``B Spline'' target transfer function interpolation procedure. The old target responses are retained for those situations where the old approach may be preferable, and may be found under the ''source/target'' directory. Of course the postfiltering stage might be used to adjust the magnitude response to taste, but for a neutral reproduction the target magnitude response should be left to the flat one. \begin{figure} \begin{center} \includegraphics[width=\basepctwidth\textwidth,keepaspectratio]{figures/DBP-DTFCmp} \caption{\label{DefaultTargetFunctions} Comparison of the main target functions provided along with DRC. } \end{center} \end{figure} The most important postfiltering target magnitude response files supplied in the standard distribution (see section \ref{PSPointsFile} ``PSPointsFile'' for details) are subultra-XX.X.txt, bk-XX.X.txt, bk-2-XX.X.txt, bk-3-XX.X.txt (see figure \ref{DefaultTargetFunctions}). Here again ''XX.X'' stands for the sample rate used and is omitted in the rest of this document. The target response files for the higher sample rates are available in the ''src/target'' directory. The first target response file provides just simple removal of overcompensation on the extremes of the frequency range and has a linear target frequency response, so it hasn't been plotted in figure \ref{DefaultTargetFunctions}. The bk.txt file follows the Bruel \& Kjaer (i.e.\ M{\oe}ller) recommendations for listening room frequency response, i.e.\ linear from 20 Hz to 400 Hz, followed by a slow decrease of 1 dB per octave up to 20 kHz. The bk-2.txt file is similar to bk.txt but it is linear up to 200 Hz and then provides a slow tilt of $0.5$ dB per octave up to 20 kHz. The bk-3.txt file is somewhat between bk-2.txt and bk.txt, with a $0.5$ dB per octave tilt above $100$ Hz. The versions with the ``sub'' suffix are the same target functions with the addition of a steep subsonic filter. The versions with the ``spline'' suffix are again the same target transfer functions but with a set of control points suitable for the ``B Spline'' target transfer function interpolation. Figure \ref{DefaultTargetFunctions} also show an example of PCHIP interpolation of the "bk-3-sub" target function. In the sample directory there are also some other simple postfiltering target files. Like the sample configuration files starting from version 2.7.0 the sample target responses are available for 44.1 kHz, 48 kHz, 88.2 kHz and 96 kHz sample rates and they must be used with the corresponding set of configuration files. By the way the target response files for higher sample rates are simply extended versions of the 44.1 kHz target responses created by simply moving the last frequency point up to the Nyquist frequency. This means that for most configuration files there is either a gentle roll-off at higher frequency or a supersonic brickwall filter applied above 20 kHz. If you want to properly correct content above 20 kHz, provided that you have a microphone capable of recording ultrasonic frequencies, you have to adapt the supplied files to your needs. \section{DRC Configuration file reference} The DRC configuration file is a simple ASCII file with parameters in the form: \begin{verbatim} ParamName = value \end{verbatim} Everything after a '{\tt \#}' and blank lines are considered comments and are ignored. Each parameter has a two character prefix which defines the step the parameter refers to. These prefixes are: \begin{itemize} \item BC = Base Configuration \item MC = Microphone Compensation stage \item HD = Homomorphic Deconvolution \item MP = Minimum phase Prefiltering stage \item DL = Dip Limiting stage \item EP = Excess phase Prefiltering stage \item PC = Prefiltering Completion stage \item IS = Inversion Stage \item PT = Psychoacoustic Target \item PL = Peak Limiting \item RT = Ringing Truncation stage \item PS = Postfiltering Stage \item MS = Minimum phase filter generation Stage \item TC = Test Convolution stage \end{itemize} DRC does some checks to ensure that each parameter provided has a value that makes sense, but it isn't bulletproof at all with respect to this. Providing invalid or incorrect parameters values may cause it to fail, or even to crash. Parameters which are important for the quality of the generated filters are marked with (*). When it makes sense a reasonable value or range of values is also provided, but the range supplied is always referred to the 44.1 kHz sample rate. Many parameters have often a value which is a power of two. This is mainly for performance reasons. Many steps require one or more FFT computations, which are usually much faster with arrays whose length is a power of two. The default values supplied are defined for a 44.1 kHz sample rate. If a different sample rate is used the supplied values should be scaled accordingly. \subsection{BC - Base Configuration} \subsubsection{BCBaseDir} \label{BCBaseDir} This parameter define the base directory that is prepended to all file parameters, like for example BCInFile, HDMPOutFile or PSPointsFile. This parameter allow the implicit definition of a library directory where all DRC support file might be placed. File parameters supplied on the command line are not affected by this parameter unless the BCBaseDir parameter is also supplied on the command line. File parameters supplied in the configuration file are instead always affected by the BCBaseDir parameter, no matter if it has been supplied in the configuration file or on the command line. \subsubsection{BCInFile} \label{BCInFile} Just the name of the input file with the input room impulse response. \subsubsection{BCInFileType} \label{BCInFileType} The type of the input file. D = Double, F = Float, I = Integer. \subsubsection{BCSampleRate} \label{BCSampleRate} The sample rate of the input file. Usually 44100 or 48000. \subsubsection{BCImpulseCenterMode} \label{BCImpulseCenterMode} The impulse response impulse center may be set manually using the BCImpulseCenter parameter or you may ask DRC to try to find it automatically. If BCImpulseCenterMode is set to A DRC will look for the impulse center within the input file. If BCImpulseCenterMode is set to M DRC uses the impulse center supplied with the BCImpulseCenter parameter. Be careful when using automatic impulse center recognition. Strong reflections or weird situations may easily fool the simple procedure used by DRC, which simply looks for the sample with the maximum absolute amplitude. \subsubsection{BCImpulseCenter (*)} \label{BCImpulseCenter} This is the position, in samples, of the time axis zero of the impulse response read from BCInFile. Usually this is where the peak of the impulse response is, but for complex situations it might not be easy to identify where the zero is. Even few samples displacement in this parameter may cause high frequency overcorrection, causing too bright sound. If BCImpulseCenterMode is set to A this parameter is ignored. \subsubsection{BCInitWindow} \label{BCInitWindow} Initial portion of the impulse response which is used to perform the correction. It should be long enough to accomodate for any subsequent windowing performed by DRC. The window is symmetrical with respect of the impulse center. If needed, the signal is padded with zeroes. Usual values are between 16384 and 131072, depending on the values of the parameters for the subsequent steps. This initial window may be further limited in subsequent steps, which sets the real window used. \subsubsection{BCPreWindowLen} \label{BCPreWindowLen} This is the length of the window used to remove any noise coming before the impulse center. This is usually just few samples, with a typical value of 1024 samples, corresponding to 23.2 ms at a 44.1 kHz sample rate. If this value is 0 this step is skipped \subsubsection{BCPreWindowGap} \label{BCPreWindowGap} This is the central flat gap left in the previous windowing operation. Usually it is set to $0.75 * BCPreWindowLen$, i.e. 768 samples with the standard BCPreWindowLen value. \subsubsection{BCNormFactor} \label{BCNormFactor} Initial normalization of the input impulse response. 0 means no normalization, which is the default. \subsubsection{BCNormType} \label{BCNormType} Type of normalization applied. M means max normalization, i.e. the input signal is rescaled so that the maximum value of the samples is equal to the normalization factor. E means Euclidean normalization (L2 Norm), i.e. the input signal is rescaled so that the RMS value of the signal is equal to the normalization factor. S means sum normalization (L1 Norm), i.e. the input signal is rescaled so that the sum of the absolute values of the samples is equal to the normalization factor. P means peak normalization i.e. the input signal is rescaled so that the highest peak in the signal magnitude response is equal to the normalization factor. \subsubsection{BCDLType, BCDLMinGain, BCDLStartFreq, BCDLEndFreq, BCDLStart, BCDLMultExponent} \label{BCDipLimiting} These parameters are used to set a mild dip limiting on the input impulse response. For a detailed description of these parameters see the similar procedure described in section \ref{DLDipLimiting}. This stage is used just to prevent overflow or underflow problems in subsequent stages so under standard conditions there is no need at all to change these parameters. \subsection{MC - Microphone Compensation} \label{MicrophoneCompensation} Within this stage the microphone transfer function is invertend and applied to the input impulse response to compensate for any microphone aberration. If you want a microphone compensated filter you have to enable this stage. The inversion is carried out by direct inversion of the values supplied in the microphone compensation file. So it is assumed that the microphone response is easily invertible. This is usually true with any decent microphone. \subsubsection{MCFilterType} \label{MCFilterType} This is the type of filter used for the microphone compensation stage stage. N means that the mic compensation stage is disabled, L means linear phase filtering, M means minimum phase filtering. \subsubsection{MCInterpolationType} \label{MCInterpolationType} This parameter is the same as the PSInterpolationType parameter (see section \ref{PSInterpolationType}) but applied to the mic compensation filter. The default is H. \subsubsection{MCMultExponent} \label{MCMultExponent} The multiplier exponent used for the homomorphic deconvolution used to compute the minimum phase compensation filter. Usually a value of 2 or 3 is used. \subsubsection{MCFilterLen} \label{MCFilterLen} Length of the FIR filter used for microphone compensation. Usually between 16384 and 65536. \subsubsection{MCNumPoints} \label{MCNumPoints} Number of points used for the definitions of the microphone frequency response. If this parameter is 0 DRC automatically counts the number of lines in the microphone frequency response file. See the following parameters for details about the microphone frequency response compensation. \subsubsection{MCPointsFile} \label{MCPointsFile} This is the name of the file which contains the microphone frequency response to be compensated. The file format is identical to the one defined for the target frequency response (see section \ref{PSPointsFile}). Again any phase specification get wiped out if minimum phase filtering is used. This usually isn't a problem because most microphones suited for measurement tasks are minimum phase systems, so the minimum phase compensation filter already has exactly the phase response needed to compensate for the microphone phase response. In the sample directory there's a sample compensation file (wm-61a.txt) which is a generic compensation file for the Panasonic WM-61A electrect capsule. This file has been derived from average values available on the Internet, so don't expect to get perfect linear frequency response using it. There could be some difference among different capsules of the same type. In the same directory there's also a compensation file for the Behringer ECM8000 instrumentation microphone. This is the measured frequency response of a single unit, i.e. it isn't even derived from an average over many samples, so it may be even less reliable than the WM-61A compensation file. \subsubsection{MCMagType} \label{MCMagType} This parameter selects how the amplitude of the target frequency response is defined. L means linear amplitude ($0.5$ means half the level, i.e about $-6$ dB), D means that the amplitude is expressed in dB. \subsubsection{MCFilterFile} \label{MCFilterFile} This parameter set the file where the impulse response of the microphone compensation filter will be saved. This might be useful to take a look at the microphone compensation filter or to use it into some other program. By default it is disabled, i.e. commented out. \subsubsection{MCOutWindow} \label{MCOutWindow} Final window after microphone compensation. Default value set to 0, i.e. no windowing applied. \subsubsection{MCNormFactor} \label{MCNormFactor} Normalization factor for the microphone compensated impulse response. Usually $0.0$, i.e. disabled. \subsubsection{MCNormType} \label{MCNormType} Normalization type for the microphone compensated impulse response. Usually E. \subsubsection{MCOutFile} \label{MCOutFile} Output file for the microphone compensated impulse response. Disabled, i.e. commented out, by default. The file generated by enabling this parameter might be used as input for the ``createdrcplots'' Octave script to generate the uncorrected response graph using a microphone compensated uncorrected response (see section \ref{SampleResults} for more details). \subsubsection{MCOutFileType} \label{MCOutFileType} Output file type for the microphone compensated impulse response. D = Double, F = Float, I = Integer. \subsection{HD - Homomorphic Deconvolution} \subsubsection{HDMultExponent} \label{HDMultExponent} Exponent of the multiplier of the FFT size used to perform the homomorphic deconvolution. The FFT size used is equal to the first power of two greater than or equal to $ BCInitWindow * (2 ^ {HDMultExponent})$. Higher exponents give more accurate deconvolution, providing less circular convolution artifacts. With older DRC versions achieving low circular artifacts was not so important because they were masked by the higher pre-echo artifacts in other steps. Starting with version 2.0.0 it is possible to achieve really low pre echo artifacts so circular artifacts now are an issue, because when truncated by the pre-echo truncation inversion procedure they may cause errors on the phase correction. In this situation a value of at least 3 is suggested. \subsubsection{HDMPNormFactor} \label{HDMPNormFactor} Normalization factor for the minimum phase component. Usually 1. \subsubsection{HDMPNormType} \label{HDMPNormType} Normalization type for the minimum phase component. Usually E. \subsubsection{HDMPOutFile} \label{HDMPOutFile} Output file for the minimum phase component. Usually not used (commented out). \subsubsection{HDMPOutFileType} \label{HDMPOutFileType} Output file type for the minimum phase component. D = Double, F = Float, I = Integer. \subsubsection{HDEPNormFactor} \label{HDEPNormFactor} Normalization factor for the excess phase component. Usually 1. \subsubsection{HDEPNormType} \label{HDEPNormType} Normalization type for the excess phase component. Usually E. \subsubsection{HDEPOutFile} \label{HDEPOutFile} Output file for the excess phase component. Usually not used (commented out). \subsubsection{HDEPOutFileType} \label{HDEPOutFileType} Output file type for the excess phase component. D = Double, F = Float, I = Integer. \subsection{MP - Minimum phase Prefiltering} \subsubsection{MPPrefilterType} \label{MPPrefilterType} This parameter can be either B for the usual band windowing prefiltering stage or S for the sliding lowpass method. The first method splits the input response into log spaced bands and window them depending on some parameters but basically with a window length which decrease exponentially with the center frequency of the band. The sliding lowpass method instead filters the impulse response with a time varying lowpass filter with a cutoff frequency which decreases exponentially with the sample position with respect to the time axis zero. This last one is a stepless procedure. Using either a lowercase b or s for the MPPrefilterType parameters enable the single side version of the prefiltering procedures. The procedure is applied starting from the impulse center, leaving the first half of the impulse response unchanged. This gives less pre-echo artifacts, and should be used when the pre-echo truncation inversion procedure is used. Please remember to set the prefiltering parameters to values which are adequate for the procedure used. \subsubsection{MPPrefilterFctn} \label{MPPrefilterFctn} This parameter sets the type of prefiltering function used, i.e. P for the usual inverse proportional function, or B for the bilinear transform based prefiltering function. For a comparison between the two functions see figure \ref{BPComparison}. The default is B. \subsubsection{MPWindowGap} \label{MPWindowGap} This parameter changes a little the window function (Blackman) used for the band windowing prefiltering stage. It sets a small flat unitary gap, whose length is expressed in samples, at the center of the window function, so that even if the impulse center is slightly misaligned with respect to the time axis zero there is no high frequency overcorrection. For band windowing prefiltering procedure usually this overcorrection is in the order of $0.1 - 0.2$ dB at 20 kHz for errors of 2 to 3 samples, so it is not important at all in real world situations, but if you want to fix even this small problem this parameter lets you do it. MPWindowGap should never be more than 2 sample less than MPUpperWindow and it is usually no more than few samples (5 to 10). If in any situation it is bigger than the calculated window DRC automatically reduces the gap to 2 less than the applied window. When MPWindowGap is 0 DRC behaves exactly as in the older versions. For the sliding lowpass procedure this sets just the window gap used for the initial windowing before the procedure starts. \subsubsection{MPLowerWindow (*)} \label{MPLowerWindow} Length of the window for the minimum phase component prefiltering at the bottom end of the frequency range. Longer windows cause DRC to try to correct a longer part of the impulse response but cause greater sensibility to the listening position. Typical values are between 16384 and 65536. MPLowerWindow must not be greater than BCInitWindow. \subsubsection{MPUpperWindow (*)} \label{MPUpperWindow} Length of the window for the minimum phase component prefiltering at the upper end of the frequency range. Longer windows cause DRC to try to correct a longer part of the impulse response but cause greater sensibility on the listening position. Typical values are between 22 and 128. MPUpperWindow must be not greater than MPLowerWindow, and usually is much shorter than that. \subsubsection{MPStartFreq} \label{MPStartFreq} Start frequency for the prefiltering stage. Usually 20 Hz or just something less. \subsubsection{MPEndFreq} \label{MPEndFreq} End frequency for the prefiltering stage. Usually set at 20 kHz, i.e. 20000. Of course you must be using a sample rate which is greater than 40 kHz to set this above 20 kHz. \subsubsection{MPWindowExponent (*)} \label{MPWindowExponent} This is the exponent used in the frequency dependent window length computation for the band windowing procedure, or in the computation of the time dependent cutoff frequency for the sliding lowpass procedure. The window length for band windowing is computed with the following expression: \begin{displaymath} W = \frac{1}{A * (F + Q) ^ {WE}} \end{displaymath} Where W is the window length, F is the normalized frequency, WE is the window exponent, A and Q are computed so that W is equal to MPLowerWindow at MPStartFreq and is equal to MPUpperWindow at MPEndFreq. If you set MPLowerWindow equal to the value used for MPInitWindow in DRC 1.2, set MPWindowExponent to the same value of version 1.2 and set MPUpperWindow to the value you got at the upper limit of the frequency range in version 1.2 you should get results much similar to the 1.2 DRC release. In a similar way the cutoff frequency for the sliding lowpass prefiltering stage is computed with: \begin{displaymath} F = \frac{1}{A * (W + Q) ^ {WE}} \end{displaymath} with identical parameters but reversed perspective, i.e. the cutoff frequency is computed from the window length and not the other way around. In both cases W and F are considered normalized between 0 and 1. These parametric functions are used when the proportional function is selected using the MPPrefilterFctn (see section \ref{MPPrefilterFctn}) parameter. The parametric functions derived from the bilinear transformation are quite different and more complicated, so they aren't explained here. Changing the window exponent provides different prefiltering curves, see section \ref{FrequencyDependentWindowing} for a deeper explanation. Increasing the window exponent gives higher correction in the midrange. Typical values are between $0.7$ and $1.2$. \subsubsection{MPFilterLen} \label{MPFilterLen} Filter length, in taps, used to perform band splitting or sliding lowpass prefiltering of the input signal. Higher values give better filter resolution but require a longer computation. Typical values for band windowing are between 4096 and 65536. Sometimes may be useful to use short filters (64 - 512 taps) to get a more ``fuzzy'' correction at lower frequencies. With the sliding lowpass procedure similar filters should be used. Usually the filter length is in the 512 - 65536 range. Short filters (16 - 64 taps) gives a similar fuzzy correction at the bottom end, but with a different behaviour than band windowing. \subsubsection{MPFSharpness (*)} \label{MPFSharpness} This parameter applies only to the sliding lowpass prefiltering procedure and control the sharpness of the filtering performed in the filtered region of the time-frequency plane. A value of 1.0 provides the same behaviour of version 2.3.1 of DRC and provides the maximum allowable filtering sharpness without affecting the direct sound, but also creates a substantial amount of spectral spreading in the filter transition region of the time-frequency plane. Values above 1.0 increase the spectral spreading up to a point where it starts affecting also the direct sound, with the introduction of some ripple in the direct sound itself. Values below 1.0 reduce the spectral spreading in the filtered region at the expense of a little reduction in the filter sharpness. Typical values for this parameter are between $0.1$ and $0.75$, with a default value of $0.25$. \subsubsection{MPBandSplit} \label{MPBandSplit} Fractional octave splitting of band windowing. Band windowing is performed in $ 1 / {MPBandSplit} $ of octave bands. Usual values are between 2 and 6. The higher this value the higher should be MPFilterLen. Values greater than 6 usually give no improvements. For the sliding lowpass prefiltering this just gives the rate at which log messages are reported during the prefiltering procedure and has no effect on the prefiltering procedure itself, which is always stepless. \subsubsection{MPHDRecover} \label{MPHDRecover} After prefiltering the minimum phase component may be no longer minimum phase, with a bit of excess phase component added. Setting this parameter to Y enable a second homomorphic deconvolution on the prefiltered minimum phase component to make it minimum phase again. This is important especially if the pre-echo truncation inversion procedure is used. This procedure assumes that the minimum phase part really is minimum phase, so skipping this step may cause it to fail in avoiding pre-echo artifacts. \subsubsection{MPEPPreserve} \label{MPEPPreserve} Setting this to Y causes the excess phase part of the filtered impulse response to be preserved after the MPHDRecover step. This excess phase part is then convolved with the excess phase part of the filtered impulse response to preserve it and invert it. This provides a slight improvement in the direct sound phase response. The default value is Y. \subsubsection{MPHDMultExponent} \label{MPHDMultExponent} Exponent of the multiplier of the FFT size used to perform the homomorphic deconvolution described above. The FFT size used is equal to the first power of two greater than or equal to $ MPPFFinalWindow * (2 ^ {MPHDMultExponent})$. Higher exponents give more accurate results, but require a longer computation. Usually a value of 2 or 3 is used. If this parameter is less than 0 no multiplier will be used. Be careful because if the FFT size isn't a power of two the procedure can take a long time to complete. \subsubsection{MPPFFinalWindow} \label{MPPFFinalWindow} Final window of the prefiltering stage. Usually the same as MPLowerWindow or just something more. If set to 0 no windowing is applied. \subsubsection{MPPFNormFactor} \label{MPPFNormFactor} Normalization factor for the minimum phase component after prefiltering. Usually $0$. \subsubsection{MPPFNormType} \label{MPPFNormType} Normalization type for the minimum phase component after windowing. Usually E. \subsubsection{MPPFOutFile} \label{MPPFOutFile} Output file for the minimum phase component after band windowing. Usually not used (commented out). \subsubsection{MPPFOutFileType} \label{MPPFOutFileType} Output file type for the minimum phase component after windowing. D = Double, F = Float, I = Integer. \subsection{DL - Dip Limiting} \label{DLDipLimiting} \subsubsection{DLType} \label{DLType} To prevent numerical instabilities during the inversion stage, deep dips in the frequency response must be limited or truncated. This parameter sets the type of dip limiting performed. L means linear phase, i.e. it applies a linear phase filter that removes dips below a given threshold, M means minimum phase, i.e. it uses a minimum phase filter to achieve the same result. Both procedures are also available with a logarithmic frequency weighting of the magnitude response, so that, for example, the 20 Hz - 200 Hz range weigths the same as the 2000 Hz - 20000 Hz range. Setting DLType to P activates the log weighted verions of the linear phase dip limiting and setting DLType to W activates the log weighted verions of the minimum phase dip limiting. Starting with version 2.0.0 DRC performs this step only on the prefiltered minimum phase part, just before performing the second homomorphic deconvolution, if enabled. So if the MPHDRecover parameter is set to Y and the MPEPPreserve parameter is set to N there is almost no difference between the two procedures, because the subsequent homomorphic deconvolution stage wipes out any phase difference giving just a minimum phase signal. Any difference would be caused just by numerical errors. \subsubsection{DLMinGain} \label{DLMinGain} This is the minimum gain allowed in the frequency response of the prefiltered signal. Values lower than this will be truncated. Typical values are between $0.1$ and $0.5$. These are absolute values with respect to the RMS value, i.e. $0.1$ is about $-20$ dB, $0.5$ is about $-6$ dB. \subsubsection{DLStartFreq} \label{DLStartFreq} Start frequency where the reference RMS level used for dip limiting is computed. \subsubsection{DLEndFreq} \label{DLEndFreq} End frequency where the reference RMS level used for dip limiting is computed. \subsubsection{DLStart} \label{DLStart} Setting this parameter to a value between $0.0$ and $1.0$ enables the ``soft clipping'' dip limiting procedure. Everything below $ DLStart * DLMinGain $, with respect to the RMS value, get rescaled so that it ends up between $ DLStart * DLMinGain $ and DLMinGain. Values for this parameter usually are between $0.5$ and $0.95$, with a typical value of $0.75$. Setting this parameter to a value equal to or greater then $1.0$ cause DRC to switch to hard clipping of the frequency response. \subsubsection{DLMultExponent} \label{DLMultExponent} Exponent of the multiplier of the FFT size used to perform the dip limiting stage. The FFT size used is equal to the first power of two greater than or equal to $ ({MPBWFinalWindow} + {EPBWFinalWindow} - 1) * (2 ^ {DLMultExponent}) $. Higher exponents give more accurate dip limiting, but requires a longer computation. Usually a value of 2 or 3 is used. If this parameter is less than 0 no multiplier will be used. Be careful because if the FFT size isn't a power of two the procedure might take a long time to complete. \subsection{EP - Excess phase Prefiltering} The excess phase prefiltering is performed pretty much the same way as the minimum phase prefiltering, so the parameters are almost identical, even though with different values. \subsubsection{EPPrefilterType} \label{EPPrefilterType} Same as MPPrefilterType but for the excess phase component. \subsubsection{EPPrefilterFctn} \label{EPPrefilterFctn} Same as MPPrefilterFctn but for the excess phase component. \subsubsection{EPWindowGap} \label{EPWindowGap} Same as MPWindowGap but for the excess phase component. \subsubsection{EPLowerWindow (*)} \label{EPLowerWindow} Same as MPLowerWindow but for the excess phase component. Typical values are between 1024 and 4096. As a rule of thumb you can take: \begin{displaymath} {EPLowerWindow} = {MPLowerWindow} / A \end{displaymath} with $A$ going from $16$ to $32$ and a typical value of $24$. EPLowerWindow must be not greater than BCInitWindow. \subsubsection{EPUpperWindow (*)} \label{EPUpperWindow} Same as MPUpperWindow but for the excess phase component. Typical values are between 22 and 128. As a rule of thumb you can take: \begin{displaymath} EPUpperWindow = MPUpperWindow \end{displaymath} \subsubsection{EPStartFreq} \label{EPStartFreq} Start frequency for the prefiltering stage. Usually 20 Hz or just something less. \subsubsection{EPEndFreq} \label{EPEndFreq} End frequency for the prefiltering stage. Usually set at 20 kHz, i.e. 20000. Of course you must be using a sample rate which is greater than 40 kHz to set this above 20 kHz. \subsubsection{EPWindowExponent (*)} \label{EPWindowExponent} Same as MPWindowExponent but for the excess phase component. See discussion on MPWindowExponent. Usual values for this parameter are between $0.5$ and $1.2$, depending on the value of EPInitWindow. As a rule of thumb you can take: \begin{displaymath} EPWindowExponent = MPWindowExponent \end{displaymath} \subsubsection{EPFilterLen} \label{EPFilterLen} Filter length, in taps, used to perform band splitting of the input signal or sliding lowpass prefiltering. Higher values gives better filter resolution but require a longer computation. Typical values for band windowing are between 4096 and 65536. Sometimes may be useful to use short filters (64 - 512 taps) to get a more ``fuzzy'' correction at lower frequencies. With the sliding lowpass procedure similar filters should be used. Usually the filter length is in the 512 - 65536 range. Short filters (16 - 64 taps) gives a similar fuzzier correction at the bottom end, but with a different behaviour than band windowing. This value is usually equal to MPFilterLen. \subsubsection{EPFSharpness (*)} \label{EPFSharpness} Same as MPFSharpness but applied to the excess phase part. \subsubsection{EPBandSplit} \label{EPBandSplit} Fractional octave splitting of band windowing. Band windowing is performed in $ 1 / {MPBandSplit} $ of octave bands. Usual values are between 2 and 6. The higher this value the higher should be MPFilterLen. Values greater than 6 usually give no improvements. For the sliding lowpass prefiltering this just gives the rate at which log messages are reported and has no effect on the prefiltering procedure, which is always stepless. This value is usually equal to MPBandSplit. \subsubsection{EPPFFinalWindow} \label{EPPFFinalWindow} Final window of the prefiltering stage. Usually the same as EPInitWindow or just something more. If set to 0 no windowing is applied. \subsubsection{EPPFFlatGain} \label{EPPFFlatGain} After band windowing the excess phase component usually need reequalization to get the flat frequency response it must have. This is the gain applied with respect to the RMS level of the signal to get this flat frequency response. Usually 1, a value of 0 disables this step. Skipping this step, i.e. setting this parameter to 0, usually gives bad results. \subsubsection{EPPFOGainFactor} \label{EPPFOGainFactor} This parameter controls how the excess phase flattening set by the previous parameter is performed. Setting this to 0 tries to get a perfectly flat excess phase component, as in version 1.3.0 of DRC. This parameter has been introduced to balance between the need of a flat excess phase response and a perfect control of the direct sound, usually achieved without any flattening. Unfortunately so far the supposed balance always proved really difficult to find in any real world situation, so this parameter is always set to 0 in the standard configuration file. The procedure has been left just for experimental purposes if some unusual situation need to be handled. Furthermore this parameter applies only to the linear phase and minimum phase excess phase flattening, it isn't available for the D type of excess phase flattening. \subsubsection{EPPFFlatType} \label{EPPFFlatType} This is the type of procedure adopted for the excess phase component renormalization. L means applying linear phase renormalization, M means applying minimum phase renormalization, D means applying another homomorphic deconvolution stage to extract just the excess phase component of the prefiltered excess phase component. L applies a linear phase filter that equalizes the excess phase amplitude response to flat, M means minimum phase, i.e. it uses a minimum phase filter to achieve the same result. The D procedure provides the same effect of the M procedure when EPPFOGainFactor is equal to $0$. Any difference is just caused by numerical errors. \subsubsection{EPPFFGMultExponent} \label{EPPFFGMultExponent} Exponent of the multiplier of the FFT size used to perform the frequency response flattening. The FFT size used is equal to the first power of two greater than or equal to $ EPBWFinalWindow * (2 ^ {EPPFFGMultExponent}) $. Higher exponents give more accurate results, but require a longer computation. This parameter should be set using the same criteria described in HDMultExponent. If this parameter is less than 0 no multiplier will be used. Be careful because if the FFT size isn't a power of two the procedure might take a long time to complete. \subsubsection{EPPFNormFactor} \label{EPPFNormFactor} Normalization factor for the excess phase component after band windowing. Usually 0, i.e. disabled. \subsubsection{EPPFNormType} \label{EPPFNormType} Normalization type for the excess phase component after windowing. Usually E. \subsubsection{EPPFOutFile} \label{EPPFOutFile} Output file for the excess phase component after windowing. Usually not used (commented out). \subsubsection{EPPFOutFileType} \label{EPPFOutFileType} Output file type for the excess phase component after windowing. D = Double, F = Float, I = Integer. \subsection{PC - Prefilter Completion} The prefilter completion stage combines the prefiltered minimum phase and excess phase parts together again. The impulse response recovered after prefilter completion defines the impulse response of the system as seen by the correction applied by DRC. \subsubsection{PCOutWindow} \label{PCOutWindow} Final window after prefiltering completion stage and before impulse inversion. This is usually between 8192 and 65536. Values greater than 65536 make no sense, giving a filter resolution lower than 1 Hz at a 44.1 kHz sample rate. Furthermore inversion of signals longer than 65536 samples may require a lot of time. Starting with version 2.0.0 this step is no longer needed with the pre-echo truncation fast deconvolution inversion method, which works directly on the minimum and excess phase components from the prefiltering stages. So if PCOutFile is not defined and ISType is set to T this step is completely skipped. \subsubsection{PCNormFactor} \label{PCNormFactor} Normalization factor for the prefiltered signal. Usually 0, i.e. disabled. \subsubsection{PCNormType} \label{PCNormType} Normalization type for the prefiltered signal. Usually E. \subsubsection{PCOutFile} \label{PCOutFile} Output file for the prefiltered signal. Usually not used (commented out). \subsubsection{PCOutFileType} \label{PCOutFileType} Output file type for the prefiltered signal. D = Double, F = Float, I = Integer. \subsection{IS - Inversion Stage} \subsubsection{ISType} \label{ISType} Type of inversion stage. L uses the usual Toeplitz least square inversion, T activates the pre-echo truncation fast deconvolution. \subsubsection{ISPETType} \label{ISPETType} This sets the type of pre echo truncation applied when ISType is T. f means a fixed pre-echo truncation, s means a time dependent pre-echo truncation applied using the usual single side sliding low-pass procedure, but with reversed behaviour, i.e. only what comes before the impulse center is processed. Starting with version 2.7.0 this is set to f and pre-echo truncation is basicly disabled because it is already carried out by the excess phase prefiltering procedure. \subsubsection{ISPrefilterFctn} \label{ISPrefilterFctn} Same as MPPrefilterFctn but for the pre-echo truncation windowing. It is used only when ISPETType is set to s. \subsubsection{ISPELowerWindow} \label{ISPELowerWindow} When ISPETType is f this is the number of samples before the impulse center where the inverted impulse response is considered pre-echo. Starting with version 2.7.0 this is is usually set to half the value of EPLowerWindow so that the pre-echo truncation procedure provides just a mild windowing. When ISPETType is s this is the number of samples considered pre-echo at the ISPEStartFreq frequency, with a typical value equal to EPLowerWindow. \subsubsection{ISPEUpperWindow} \label{ISPEUpperWindow} When ISPETType is f this is the number of samples before the impulse center where the pre-echo region, defined by the previous parameter, ends, and the full impulse response of the inverted filter should start. Starting with version 2.7.0 this is usually set to about $0.75 * ISPELowerWindow$ so that the pre-echo truncation procedure is limited to a mild windowing used only to avoid small steps in the impulse response attack caused by small numerical errors. When ISPETType is s this is the number of sample considered pre-echo at the ISPEEndFreq frequency, with a typical value equal to EPUpperWindow. \subsubsection{ISPEStartFreq} \label{ISPEStartFreq} Start frequency for the sliding low pass pre-echo truncation procedure. Usually 20 Hz. Used only when ISPETType is s. \subsubsection{ISPEEndFreq} \label{ISPEEndFreq} End frequency for the sliding low pass pre-echo truncation procedure. Usually 20000 Hz. Used only when ISPETType is s. \subsubsection{ISPEFilterLen} \label{ISPEFilterLen} Length of the filter used for the pre-echo truncation sliding lowpass procedure. Usually 8192. Used only when ISPETType is s. \subsubsection{ISPEFSharpness} \label{ISPEFSharpness} Same as MPFSharpness, but applied to the inversion stage pre-echo truncation. Here slightly bigger values usually provide better results because of the shorter windowing. Used only when ISPETType is s. The default value is $0.5$. \subsubsection{ISPEBandSplit} \label{ISPEBandSplit} For the sliding lowpass prefiltering this just gives the rate at which log messages are reported and has no effect on the prefiltering procedure, which is always stepless. Used only when ISPETType is s. \subsubsection{ISPEWindowExponent} \label{ISPEWindowExponent} Window exponent applied to the pre-echo truncation sliding lowpass procedure. Usual values goes from $0.5$ to $1.5$, with a typical value of $1.0$. Used only when ISPETType is s. \subsubsection{ISPEOGainFactor} \label{ISPEOGainFactor} This parameter has the same effect of the EPPFOGainFactor (see section \ref{EPPFOGainFactor}) but applied to the renormalization of the excess phase part of the inverse filter after pre-echo truncation. Used in conjunction with the EPPFOGainFactor parameter, this parameter can be used to balance the amount of correction applied to the direct sound compared to the amount of correction applied to the reverberant field. A negative value disables the renormalization. Default is $0.0$. \subsubsection{ISSMPMultExponent} \label{ISSMPMultExponent} This is the exponent of the multiplier for the S inversion stage, using the longest of the input and output signals as a basis. This parameter should be set using the same criterion used for the MPHDMultExponent parameters and a values of at least 3 is suggested. \subsubsection{ISOutWindow} \label{ISOutWindow} Final window after inversion stage. Usually 0, i.e. disabled, with the L type inversion stage. With the S type this is the output filter size and can be any length but usually is between 8192 and 65536. If it is 0 than a length equal to $ {MPPFFinalWindow} + {EPPFFinalWindow} - 1 $, i.e. the length of the convolution of the two components together, is assumed and no windowing is applied to the output filter. \subsubsection{ISNormFactor} \label{ISNormFactor} Normalization factor for the inverted signal. Usually 0, i.e. disabled. \subsubsection{ISNormType} \label{ISNormType} Normalization type for the inverted signal. Usually E. \subsubsection{ISOutFile} \label{ISOutFile} Output file for the inverted signal. Usually not used (commented out). \subsubsection{ISOutFileType} \label{ISOutFileType} Output file type for the inverted signal. D = Double, F = Float, I = Integer. \subsection{PT - Psychoacoustic Target} \label{PTPsychoacousticTarget} This stage computes a psychoacoustic target response based on the magnitude response envelope. \subsubsection{PTType} \label{PTType} Defines the type of psychoacoustic target filter to use. N means no filter, thus skipping the psychoacoustic target stage completely. M means that a minimum phase filter is used and L means that a linear phase filter is used. The default is M. \subsubsection{PTReferenceWindow (*)} \label{PTReferenceWindow} This parameter define the size used to window the corrected impulse response. The windowed response is then used to compute the magnitude response envelope that the target response is based upon. Usually a portion of the impulse response going from 150 ms to 500 ms is used. The default value is 26460, corresponding to a symmetric window, 300 ms long on each side, at 44100 Hz sample rate. \subsubsection{PTDLType, PTDLMinGain, PTDLStartFreq, PTDLEndFreq, PTDLStart, PTDLMultExponent} \label{PTDipLimiting} These parameters are used to set a small dip limiting on the corrected impulse response in order to avoid numerical problems in the inversion of the magnitude response envelope. For a detailed description of these parameters see the similar procedure described in section \ref{DLDipLimiting}. This stage is used just to prevent overflow or underflow problems so under standard conditions there is no need at all to change these parameters. \subsubsection{PTBandWidth (*)} \label{PTBandWidth} This parameter define the resolution used for the computation of the magnitude response envelope. It is defined as fraction of octaves, so a value of 0.25 means a resolution of 1/4 of octave. Values below 0 down to -1 causes the adoption of the Bark scale, values below -1 causes the adoption of the ERB scale. The default value is -2, which means that the computation is performed on the ERB scale. \subsubsection{PTPeakDetectionStrength (*)} \label{PTPeakDetectionStrength} This parameter define how close the magnitude response envelope will be to to the peaks in the unsmoothed spectrum. Higher values provide a closer match. Typical values are between 5 and 30, with the default value, based on documented psychoacoustic assumptions, set to 15. Values above 50 are probably going to cause numerical problems and should be avoided. \subsubsection{PTMultExponent} \label{PTMultExponent} Multiplier exponent for the computation of the magnitude response envelope. Default is 0. \subsubsection{PTFilterLen} \label{PTFilterLen} Length of the psychoacoustic target filter. Default set to 65536. \subsubsection{PTFilterFile} \label{PTFilterFile} Output file for the psychoacoustic target filter. Usually not used (commented out). \subsubsection{PTFilterFileType} \label{PTFilterFileType} Output file type for the psychoacoustic target filter. D = Double, F = Float, I = Integer. \subsubsection{PTNormFactor} \label{PTNormFactor} Normalization factor for the inverted signal after convolution with the psychoacoustic target filter. Usually 0, i.e. disabled. \subsubsection{PTNormType} \label{PTNormType} Normalization type for the inverted signal after convolution with the psychoacoustic target filter. Usually E. \subsubsection{PTOutFile} \label{PTOutFile} Output file for the inverted signal after convolution with the psychoacoustic target filter. Usually not used (commented out). \subsubsection{PTOutFileType} \label{PTOutFileType} Output file type for the inverted signal after convolution with the psychoacoustic target filter. D = Double, F = Float, I = Integer. \subsubsection{PTOutWindow} \label{PTOutWindow} Normalization factor for the inverted signal after convolution with the psychoacoustic target filter. Usually 0, i.e. disabled. \subsection{PL - Peak Limiting} The peak limiting stage limits the maximum allowed gain of the filter to prevent amplification and speaker overload. \subsubsection{PLType} \label{PLType} Type of peak limiting applied. L means linear phase, M means minimum phase, P means log weighted linear phase, W means log weighted minimum phase. For an explanation of the log weighted versions of the procedures see section \ref{DLType}. If PSFilterType is set to T PLType should be set to M or W to ensure that the initial zero valued part is preserved. Since version 3.1.2 the default and suggested value for this parameter is W. \subsubsection{PLMaxGain} \label{PLMaxGain} Maximum gain allowed in the correction filter. Peaks in the correction filter amplitude response greater than this value will be compressed to PLMaxGain. Typical values are between 1.2 and 4. These are absolute values with respect to the RMS value, i.e. 1.2 is about 1.6 dB and 4 is about 12 dB. This peak limiting stage is used to prevent speaker or amplifier overloading, resulting in dynamic range limitations which are subjectively worse than some narrow dip in the frequency response. A typical value is 2.0, i.e. 6 dB. \subsubsection{PLStart} \label{PLStart} Setting this parameter to a value between $0.0$ and $1.0$ enables the ``soft clipping'' peak limiting procedure. Everything above $ {PLStart} * {PLMaxGain} $, with respect to the RMS value, get rescaled so that it ends up between $ {PLStart} * {PLMaxGain} $ and about PLMaxGain. Values for this parameter usually are between $0.5$ and $0.95$, with a typical value of $0.75$. Setting this parameter to a value equal to or greater than $1.0$ switch to hard clipping of the magnitude response. \subsubsection{PLStartFreq} \label{PLStartFreq} Start frequency where the reference RMS level used for peak limiting is computed. Default value set to 100 Hz. This value should be set typically to something like an octave above the minimum reproducible frequency of your speakers. \subsubsection{PLEndFreq} \label{PLEndFreq} End frequency where the reference RMS level used for peak limiting is computed. Default value set to 10000 Hz. This value should be set typically to something like an octave below the maximum reproducible frequency of your speakers. \subsubsection{PLMultExponent} \label{PLMultExponent} Exponent of the multiplier of the FFT size used to perform the peak limiting stage. The FFT size used is equal to the first power of two greater than or equal to $ {PSOutWindow} * (2 ^ {PLMultExponent}) $. Higher exponents give more accurate peak limiting, but requires a longer computation. Usually a value of 2 or 3 is used. If this parameter is less than 0 no multiplier will be used. Be careful because if the FFT size isn't a power of two the procedure can take a long time to complete. \subsubsection{PLOutWindow} \label{PLOutWindow} Final window after peak limiting. Usually 0, i.e. disabled. \subsubsection{PLNormFactor} \label{PLNormFactor} Normalization factor for the final filter. Usually 0, i.e. disabled. \subsubsection{PLNormType} \label{PLNormType} Normalization type for the peak limited filter, usually E. \subsubsection{PLOutFile} \label{PLOutFile} Output file for the peak limited filter. Usually disabled (commented out). \subsubsection{PLOutFileType} \label{PLOutFileType} Output file type for the final filter. D = Double, F = Float, I = Integer. \subsection{RT - Ringing Truncation} \label{RingingTruncation} The ringing truncation stage applies a further frequency dependent windowing to the correction filter. The truncation parameters are pretty similar to those of the prefiltering stage and usually have also much similar values. \subsubsection{RTType} \label{RTType} This parameter can be either B or b for the band windowing method, S or s for the sliding lowpass method or N to disable the ringing truncation stage. See section \ref{FrequencyDependentWindowing} and \ref{MPPrefilterType} for further details. \subsubsection{RTPrefilterFctn} \label{RTPrefilterFctn} Same as MPPrefilterFctn but for the ringing truncation windowing. \subsubsection{RTWindowGap} \label{RTWindowGap} This parameter changes a little the window function (Blackman) used for the band windowing or the sliding lowpass windowing. See section \ref{MPWindowGap} for further details. \subsubsection{RTLowerWindow (*)} \label{RTLowerWindow} Length of the window at the bottom end of the frequency range. Usually set to the same value of MPLowerWindow. \subsubsection{RTUpperWindow (*)} \label{RTUpperWindow} Length of the window at the upper end of the frequency range. Usually set to the same value of MPUpperWindow. \subsubsection{RTStartFreq} \label{RTStartFreq} Start frequency for the windowing. Usually 20 Hz or just something less. \subsubsection{RTEndFreq} \label{RTEndFreq} End frequency for the windowing. Usually set to 20000. \subsubsection{RTWindowExponent (*)} \label{RTWindowExponent} This is the exponent used in the frequency dependent window length computation for the band windowing procedure, or in the computation of the time dependent cutoff frequency for the sliding lowpass procedure. See section \ref{MPWindowExponent} for further details. Usually set to the same value of MPWindowExponent. \subsubsection{RTFilterLen} \label{RTFilterLen} Filter length, in taps, used to perform band splitting or sliding lowpass prefiltering of the input signal. Usually the same as the one used in the prefiltering stage. \subsubsection{RTFSharpness (*)} \label{RTFSharpness} This parameter applies only to the sliding lowpass prefiltering procedure and control the sharpness of the filtering performed in the filtered region of the time-frequency plane. See section \ref{MPFSharpness} for further details. \subsubsection{RTBandSplit} \label{RTBandSplit} Fractional octave splitting of band windowing. See section \ref{MPBandSplit} for further details. \subsubsection{RTOutWindow} \label{RTOutWindow} Final window of the stage. Usually set to 0, i.e. disabled. \subsubsection{RTNormFactor} \label{RTNormFactor} Normalization factor for the minimum phase component after windowing. Usually $0$. \subsubsection{RTNormType} \label{RTNormType} Normalization type for the minimum phase component after windowing. Usually E. \subsubsection{RTOutFile} \label{RTOutFile} Output file for the filter after windowing. Usually not used (commented out). \subsubsection{RTOutFileType} \label{RTOutFileType} Output file type for the filter after windowing. D = Double, F = Float, I = Integer. \subsection{PS - Postfiltering Stage} \label{PostfilteringStage} During the postfiltering stage the final target transfer function is applied to the filter and the filter is normalized to suitable values for the convolver used. \subsubsection{PSFilterType} \label{PSFilterType} This is the type of filter used for the postfiltering stage. L means the usual linear phase filtering, M means minimum phase filtering, T means minimum phase filtering with initial zero truncation. If the pre-echo truncation inversion is used and the final post filtering stage is minimum phase all the filter taps before ISPELowerWindow are zero (there could be some roundoff errors that make them different from zero, but considering them zero makes no difference for our needs). So this initial all zero part can be windowed out without changing the filter behaviour. This way the filter becomes almost zero delay, providing a delay of just ISPELowerWindow samples. This sometimes may be low enough to make it usable even with home theater systems where audio delay is a major issue. Of course to ensure that the initial all zero part is preserved the minimum phase peak limiting should also be used. \subsubsection{PSInterpolationType} \label{PSInterpolationType} This parameter defines the type of interpolation used between the points of the target transfer function. L means the usual linear interpolation, G means logarithmic interpolation, i.e. interpolation performed on a bilogarithmic scale, R means interpolation using Uniform Cubic B Splines, S means interpolation using Uniform Cubic B Splines on a bilogarithmic scale, P means interpolation on a linear scale using a monotone Piecewise Cubic Hermite Interpolating Polynomial (PCHIP), H means interpolation on a logarithmic scale using PCHIP. The logarithmic interpolation makes the definition of the target transfer function easier, without the need to define intermediate points to get the desired behaviour on a bilogarithmic scale. The default is S. The B Splines interpolation options allow for the definition of smooth target transfer functions which provides less ringing. Be careful when using this option because defining the right control points to get the desired target transfer function might be tricky. B Splines don't interpolate the supplied points but are instead tangent to the lines connecting the control point. If you want sharp corners in the transfer function just place few close control points near to the desired corner. Remember that B Splines of the type used are unaffected by control points which are more than two control points away from any given point on the curve. Take a look at the supplied examples for some simple transfer function definition. The PCHIP procedure provides a monotonic interpolation procedure. The resulting target is less smooth than the one supplied by B Splines, but being a true interpolation PCHIP makes the definition of the control points much easier. The use of the B Spline or PCHIP interpolation procedures is often useful also for the definition of the mic compensation transfer function, especially when only few points are available. \subsubsection{PSMultExponent} \label{PSMultExponent} The multiplier exponent used for the homomorphic deconvolution used to compute the minimum phase post filter. Usually a value of 2 or 3 is used. \subsubsection{PSFilterLen} \label{PSFilterLen} Length of the FIR filter used during the postfiltering stage. Usually between 16384 and 65536. \subsubsection{PSNumPoints} \label{PSNumPoints} Number of points used for the definition of the post filter frequency response. If this parameter is 0 DRC automatically counts the number of lines in the post filter definition file. See the following parameters for further details about the post filter frequency response. \subsubsection{PSMagType} \label{PSMagType} This parameter selects how the amplitude of the target frequency response is defined. L means linear amplitude ($0.5$ means half the level, i.e about $-6$ dB), D means that the amplitude is expressed in dB. \subsubsection{PSPointsFile (*)} \label{PSPointsFile} File containing the post filter frequency response definition. This file should contain PSNumPoints lines, each line in the form ``Frequency Gain'', with the gain expressed as a linear gain or in dB depending on the PSMagType parameter value. The following examples are in dB. The first line must have a frequency equal to 0, the last line must have a frequency equal to $ {BCSampleRate} / 2 $. A post filter definition file must have the following format: \begin{quote} \begin{verbatim} 0 -40 18 -20 20 0 20000 0 21000 -40 22050 -100 \end{verbatim} \end{quote} This is for a 44.1 kHz sample rate. The post filter stage is usually used to prevent overcompensation in the subsonic or ultrasonic range, but may be used also to change the target frequency response from linear to a more euphonic one. Starting from version 2.0.0 DRC lets you specify the phase for the target post filter stage. Phase specification should be placed after the amplitude specification and should be expressed in degrees. Following the example above: \begin{quote} \begin{verbatim} 0 -40 0 18 -20 45 20 0 90 20000 0 180 21000 -40 90 22050 -100 0 \end{verbatim} \end{quote} If not specified a value of 0 is assumed. Setting a phase different than 0, i.e. flat, is useless within normal HiFi systems in almost all circumstances. Furthermore the phase specification is used only if the PSFilterType is L, else any phase specification is wiped out by the minimum phase filter extraction. \subsubsection{PSOutWindow} \label{PSOutWindow} Final window after post filtering. This is also the length of the generated correction filter. Usual values are between 8192 and 65536. Filter with 65536 taps gives about $0.5$ Hz resolution at $44.1$ kHz sample rate, 16384 is usually enough for most situation and 8192 gives somewhat good results with much less computing needs during real time convolution. \subsubsection{PSNormFactor} \label{PSNormFactor} Normalization factor for the correction filter. Usually $1.0$. See section \ref{PreventingClipping} for some instructions on how to set this parameter. \subsubsection{PSNormType} \label{PSNormType} Normalization type for the correction filter. Usually E. See section \ref{PreventingClipping} for some instructions on how to set this parameter. \subsubsection{PSOutFile} \label{PSOutFile} Output file for the correction filter. This file contains the filter to be used with the convolution engine. \subsubsection{PSOutFileType} \label{PSOutFileType} Output file type for the correction filter. D = Double, F = Float, I = Integer. \subsection{MS - Minimum phase filter extraction Stage} The minimum phase extraction stage creates a minimum phase filter from the correction filter. A minimum phase filter corrects just the magnitude response and the minimum phase part of the phase response, but it is usually almost artifacts free and as basically zero latency. If microphone compensation is enabled the filter includes microphone compensation. \subsubsection{MSMultExponent} \label{MSMultExponent} Exponent of the multiplier for the homomorphic deconvolution used to extract a zero delay minimum phase version of the correction filter. A value of 2 or 3 is usually enough. \subsubsection{MSOutWindow} \label{MSOutWindow} Output window size for the minimum phase filter. Typical values are about half of PLOutWindow. \subsubsection{MSFilterDelay} \label{MSFilterDelay} This parameter add an initial delay to the filter, making it possible to align it with other filters. Usually it is set to the same value assigned to EPLowerWindow, so that the filter has the same latency of the mixed phase filter when PSFilterType is set to T. If you want a zero delay filter set this parameter to 0. \subsubsection{MSNormFactor} \label{MSNormFactor} Normalization factor for the minimum phase filter. The same considerations of section \ref{PreventingClipping} should be applied. \subsubsection{MSNormType} \label{MSNormType} Normalization type for the minimum phase filter. Usually E. See section \ref{PreventingClipping} for some instructions on how to set this parameter. \subsubsection{MSOutFile} \label{MSOutFile} Output file name for the minimum phase filter. \subsubsection{MSOutFileType} \label{MSOutFileType} Output file type for the minimum phase filter. \subsection{TC - Test Convolution} \subsubsection{TCNormFactor} \label{TCNormFactor} Normalization factor for the output of the final convolution stage. Usually $0.0$. \subsubsection{TCNormType} \label{TCNormType} Normalization type for the output of the final convolution stage. Usually E. \subsubsection{TCOutFile} \label{TCOutFile} Output file for the final test convolution. If this is not supplied the test convolution stage is skipped. \subsubsection{TCOutFileType} \label{TCOutFileType} Output type for the file above. D = Double, F = Float, I = Integer. \section{Acknowledgments} DRC grew up with the contribution of many peoples. The list is really long, and there's some chance that I'm forgetting someone. By the way here it is the list, in random order: \begin{itemize} \item Thanks to Prof. Angelo Farina and Prof. John Mourjopoulos for their papers released in the public domain. Many DRC algorithms started from references and explanations found in those papers. \item Many thanks to Anders Torger for his BruteFIR package and his suggestions. Without BruteFIR DRC would have been just a programming exercise, and I would have never started writing it. Anders also gave me the idea of the sliding lowpass prefiltering procedure. \item Many thanks to ``Jaco the Relentless'' for his enthusiastic support and for all the tests on his own HiFi system. \item Thanks to Maurizio Mulas for sending me the impulse response of his room as a testbed for some releases and for all his listening tests. \item Thanks to Marco Bagna and Alex ``Flex'' Okely for their support during the DRC development and also for letting me testing DRC on their high quality HiFi systems. \item Thanks to Michele Spinolo for his enthusiastic support and for writing some documentation about DRC and its functionalities. \item Many thanks to ``Jones Rush'' for all his efforts understanding how DRC works and for writing a good step by step DRC guide, something that was really missing. \item Many thanks to Tom Browne for his suggestions and tests on his own system and his help in optimizing the DRC performances. \item Many thanks to Ed Wildgoose for his suggestions and tests on his own system, for providing the perl script which glsweep is based upon and for setting up the DRC Wiki pages. \item Thanks to Ulrich ``Uli'' Brueggemann for providing some filters generated with a completely different approach. Most of the changes of version 2.5.0 have been implemented after comparing the DRC filters with those filters. \item Thanks to Chris Birkinshaw for providing the Jack version of the automatic measuring script. \item Thanks to Gregory Maxwell for writing the excellent Wikipedia digital room correction article. \item Many thanks to the ALSA team for providing a good Linux sound infrastructure and for helping fixing some nasty bugs in the TerraTec EWX 24/96 driver. \item Many thanks to the \TeX, \LaTeX, Octave, GNUPlot and HeVeA developers for providing the invaluable tools used to create this document. \end{itemize} Finally many thanks to all the peoples who have contributed to DRC, sometimes without even knowing it. Most of the ideas used to develop DRC come from public papers, algorithms and source code found for free over the Internet. \section{Similar software} There are other software packages providing functionalities similar or comparable to those of DRC. Here are some examples: \begin{itemize} \item Acourate: \url{http://www.acourate.com/} \item Room Eq Wizard: \url{http://www.hometheatershack.com/roomeq/} \item Audiolense: \url{http://www.juicehifi.com/} \end{itemize} \appendix \clearpage \section{Sample results} \label{SampleResults} In the following pages some graphs with a comparison between the corrected and uncorrected system are reported. This is of course just a sample situation and describes what I achieved in my own system. My uncorrected system show performance figures which are quite uncommon, partly because it is placed in an heavily damped listening room but mostly because it has been tuned to give its best with the correction in place. So the results for the uncorrected system shouldn't be taken as an example of typical behaviour. The results of the corrected system show instead the perfomance levels achievable combining active room correction with traditional passive room treatment. Depending on the behaviour of the speakers and the listening room, and on the settings used for DRC, the results could be quite different. The results presented have been obtained with the psychoacoustic target stage disabled. All the graphs presented in these section are based on traditional objective evaluation of the system transfer function. No psychoacoustics is involved in the graphs generation procedures, so the results with the psychoacoustic target cannot be evaluated using this kind of graphs. On the other hand the proposed graphs clearly show that the correction is able to closely match the supplied target, so proving that any psychoacoustic target computation would be closely followed by the correction. This implies that, if the underlying psychoacoustic model is correct, the results will be as expected. All the graphs, except the spectrograms and other 3D plots, follow the same conventions. The uncorrected system is reported with red lines and the corrected system is reported with blue lines. The spectrograms and the 3D plots need a specific colormap for proper visualization, which is of course the same for both the corrected and uncorrected system, so they can't follow this simple convention. All the graphs have been prepared with the Octave files available under the ``src/doc/octave'' directory of the standard distribution. The ``createdrcplots.m'' file contains a function which creates all the graphs needed to compare two impulse responses and saves them into encapsulated postscript files or files in any other format supporte by Octave. To load the raw pcm files created by DRC you can use the ``loadpcm'' function with some Octave commands like: \begin{quote} {\scriptsize \begin{verbatim} ru = loadpcm("/pathtopcm/rmc.pcm"); rc = loadpcm("/pathtopcm/rtc.pcm"); \end{verbatim} } \end{quote} The uncorrected response could be obtained by uncommenting the MCOutFile parameter and setting it properly. If you don't have a microphone compensation file you can simply use the flat target response to provide a null compensation and get the needed output file only. The corrected response could be obtained by uncommenting the TCOutFile parameter and setting it properly. Then the full sets of graphs will be created with an Octave command like: \begin{quote} {\scriptsize \begin{verbatim} createdrcplots(ru,-1,"R Uncorrected",rc,-1,"R Corrected","/pathtographs/","R"); \end{verbatim} } \end{quote} Graph in a different format than the standard encapsulated postscript may be easily obtained by suppling some further parameters to the createdrcplots procedure. For example to create the graphs in PNG format a command like this might be used: \begin{quote} {\scriptsize \begin{verbatim} createdrcplots(ru,-1,"R Uncorrected",rc,-1,"R Corrected","/pathtographs/","R",".png","-dpng"); \end{verbatim} } \end{quote} All formats supported by the Octave print command may be used. Se the Octave documentation for further details. You need at least Octave 3.2.3, along with the Octave-Forge packages ``signal'', and GnuPlot version 4.3 or newer, for these scripts to work. The scripts have been tested with octave 4.2.1 and GnuPlot 5.0.5. Beware that the latest versions of Octave don't use Gnuplot as the default plotting toolkit so you might need to issue a command like: \begin{quote} {\scriptsize \begin{verbatim} graphics_toolkit('gnuplot'); \end{verbatim} } \end{quote} before running the supplied commands to get the scripts working. Octave can be downloaded from: \begin{quote} \url{http://www.octave.org/} \end{quote} Michele Spinolo prepared a \LaTeX\ document which packages the full set of graphs into a single file. The \LaTeX\ script is named ``drc-graphs.tex'' and is available under the ``src/doc'' directory. The script could be used for pdf or postscript file creation, or to create HTML files using HeVeA, and maybe also wiht Latex2Html. The graphs should be created using ``T'' as the graphs prefix name in the ``createdrcplots'' function above, else you have to edit the header of the script to change the graph prefix. HeVeA and Latex2Html are available at the following sites: \begin{quote} \url{http://www.latex2html.org/}\newline \url{http://pauillac.inria.fr/~maranget/hevea/} \end{quote} \subsection{Time response} \label{SampleResultsTimeResponse} The first series of graphs show the effect of the correction in the time domain. The correction provides a clear improvement in the time response, with an effect that becomes longer and longer in time as the frequency decrease, as expected. \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IRStepResponse} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IRStepResponse} \caption{\label{StepResponseFullRange} Corrected and uncorrected step response comparison. The corrected step response is much closer to the expected exponential decay than the uncorrected one, at least up to above 10 ms.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IRFullRange} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IRFullRange} \caption{\label{ImpulseResponseFullRange} Corrected and uncorrected impulse response comparison. The corrected impulse response becomes much similar to a (minimum phase) bandlimited Dirac spike for about 1 ms. This implies a close to perfect phase response at least for the early direct sound.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IRFullRangeEnvelope} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IRFullRangeEnvelope} \caption{\label{EnvelopeFullRange} Impulse response envelope for the corrected and uncorrected system.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IRFullRangeETC} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IRFullRangeETC} \caption{\label{ETCFullRange} Time-energy response (impulse response envelope plotted with a logarithmic magnitude scale) for the corrected and uncorrected system.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IR2kHzBrickwall} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IR2kHzBrickwall} \caption{\label{ImpulseResponse2kHzBrickwall} Corrected and uncorrected impulse response comparison. The impulse responses have been brickwall filtered at 2 kHz to show the increased effect up to the midrange.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IR2kHzBrickwallEnvelope} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IR2kHzBrickwallEnvelope} \caption{\label{Envelope2kHzBrickwall} Impulse response envelope for the corrected and uncorrected system. The impulse responses have been brickwall filtered at 2 kHz to show the increased effect up to the midrange.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IR2kHzBrickwallETC} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IR2kHzBrickwallETC} \caption{\label{ETC2kHzBrickwall} Time-energy response (impulse response envelope plotted with a logarithmic magnitude scale) for the corrected and uncorrected system. The impulse responses have been brickwall filtered at 2 kHz to show the increased effect up to the midrange.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IR200HzBrickwall} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IR200HzBrickwall} \caption{\label{ImpulseResponse200HzBrickwall} Corrected and uncorrected impulse response comparison. The impulse responses have been brickwall filtered at 200 Hz to show the further increased effect in the bassrange.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IR200HzBrickwallEnvelope} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IR200HzBrickwallEnvelope} \caption{\label{Envelope200HzBrickwall} Impulse response envelope for the corrected and uncorrected system. The impulse responses have been brickwall filtered at 200 Hz to show the further increased effect in the bassrange.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-IR200HzBrickwallETC} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-IR200HzBrickwallETC} \caption{\label{ETC200HzBrickwall} Time-energy response (impulse response envelope plotted with a logarithmic magnitude scale) for the corrected and uncorrected system. The impulse responses have been brickwall filtered at 200 Hz to show the further increased effect in the bassrange.} \end{center} \end{figure} \clearpage \subsection{Frequency response} \label{SampleResultsFrequencyResponse} These series of graphs show the effect of the correction on the frequency response magnitude for some different windows applied to the time response and with different kind of smoothing applied. \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRUnsmoothed1ms} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRUnsmoothed1ms} \caption{\label{MagnitudeUnsmoothed1ms} Unsmoothed frequency response magnitude, 1 ms Blackman window. These graphs show the frequency response of the early direct sound.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRUnsmoothed5ms} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRUnsmoothed5ms} \caption{\label{MagnitudeUnsmoothed5ms} Unsmoothed frequency response magnitude, 5 ms Blackman window. These graphs show the frequency response of the direct sound.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRUnsmoothed200ms} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRUnsmoothed200ms} \caption{\label{MagnitudeUnsmoothed200ms} Unsmoothed frequency response magnitude, bass range, 200 ms Blackman window. These graphs show the frequency response of the bass range over a 200 ms time window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRFDWSmoothed} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRFDWSmoothed} \caption{\label{MagnitudeFDWSmoothedNormal} Frequency response magnitude smoothed using a frequency dependent windowing with windowing settings close to those used by the normal.drc sample configuration file.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRFDWSmoothed-1-6} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRFDWSmoothed-1-6} \caption{\label{MagnitudeFDWSmoothed16Oct} Frequency response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/6 of octave smoothing.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRFDWSmoothed-1-3} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRFDWSmoothed-1-3} \caption{\label{MagnitudeFDWSmoothed13Oct} Frequency response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/3 of octave smoothing.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRBarkSmoothed} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRBarkSmoothed} \caption{\label{MagnitudeBarkSmoothed} Frequency response magnitude smoothed over the Bark psychoacoustic scale with many different Blackman windows applied.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MRERBSmoothed} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MRERBSmoothed} \caption{\label{MagnitudeERBSmoothed} Frequency response magnitude smoothed the ERB psychoacoustic scale with many different Blackman windows applied.} \end{center} \end{figure} \clearpage \subsection{Phase response} \label{PhaseResponse} This section show some phase response graphs. The phase response becomes basicly linear at least for the direct sound, which implies also a constant group delay. \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-PRUnsmoothed1ms} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-PRUnsmoothed1ms} \caption{\label{PhaseResponse1} Unsmoothed phase response, 1 ms Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-PRUnsmoothed5ms} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-PRUnsmoothed5ms} \caption{\label{PhaseResponse5} Unsmoothed phase response, 5 ms Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-PRUnsmoothed200ms} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-PRUnsmoothed200ms} \caption{\label{PhaseResponse200} Unsmoothed phase response, bass range, 200 ms Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-PRFDWSmoothed} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-PRFDWSmoothed} \caption{\label{PhaseFDWSmoothedNormal} Phase response smoothed using a frequency dependent windowing with windowing settings close to those used by the normal.drc sample configuration file.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-PRFDWSmoothed-1-6} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-PRFDWSmoothed-1-6} \caption{\label{PhaseFDWSmoothed16Oct} Phase response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/6 of octave smoothing.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-PRFDWSmoothed-1-3} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-PRFDWSmoothed-1-3} \caption{\label{PhaseFDWSmoothed13Oct} Phase response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/3 of octave smoothing.} \end{center} \end{figure} \clearpage \subsection{Time-frequency analysis} \label{TimeFrequencyAnalysis} In this section some joint time-frequency analysis results are presented. Time-frequency graphs are more difficult to understand than the graphs presented so far, but they provide also invaluable information about how the system under test is working. The human ear works using a joint time-frequency analysis too, so these graphs provide a representation of the system behaviour that is much closer to our subjective perception. Many graphs show the spectral decay of the system. The spectral decay isn't exactly the same as the cumulative spectral decay (CSD) often used for loudspeaker analysis, even though it is strictly related to it. The spectral decay is obtained using an oversampled short-time Fourier transform of the impulse response, being careful to use a window that is long enough to satisfy the Gabor inequality (see section \ref{FrequencyDependentWindowing} and figure \ref{Gabor} for details). The correct interpretation of the graphs presented in this section would require a book by itself, so little words are spent describing the results achieved. With respect to this any comment is welcome. \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SDHighRange} \caption{\label{SpectralDecayHRL} Left channel, spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SDHighRange} \caption{\label{SpectralDecayHRR} Right channel, spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SFHighRange} \caption{\label{SpectralFormationHRL} Left channel, spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SFHighRange} \caption{\label{SpectralFormationHRR} Right channel, spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SDMidRange} \caption{\label{SpectralDecayMRL} Left channel, spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SDMidRange} \caption{\label{SpectralDecayMRR} Right channel, spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SFMidRange} \caption{\label{SpectralFormationMRL} Left channel, spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SFMidRange} \caption{\label{SpectralFormationMRR} Right channel, spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SDBassRange} \caption{\label{SpectralDecayBRL} Left channel, spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 50 ms sliding Blackman window. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SDBassRange} \caption{\label{SpectralDecayBRR} Right channel, spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 50 ms sliding Blackman window. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SFBassRange} \caption{\label{SpectralFormationBRL} Left channel, spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 50 ms sliding Blackman window. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SFBassRange} \caption{\label{SpectralFormationBRR} Right channel, spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 50 ms sliding Blackman window. } \end{center} \end{figure} \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SDHighRangeW} \caption{\label{SpectralDecayHRLW} Left channel, spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SDHighRangeW} \caption{\label{SpectralDecayHRRW} Right channel, spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SFHighRangeW} \caption{\label{SpectralFormationHRLW} Left channel, spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SFHighRangeW} \caption{\label{SpectralFormationHRRW} Right channel, spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SDMidRangeW} \caption{\label{SpectralDecayMRLW} Left channel, spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SDMidRangeW} \caption{\label{SpectralDecayMRRW} Right channel, spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SFMidRangeW} \caption{\label{SpectralFormationMRLW} Left channel, spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SFMidRangeW} \caption{\label{SpectralFormationMRRW} Right channel, spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SDBassRangeW} \caption{\label{SpectralDecayBRLW} Left channel, spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 100 ms sliding Blackman window. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SDBassRangeW} \caption{\label{SpectralDecayBRRW} Right channel, spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 100 ms sliding Blackman window. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-SFBassRangeW} \caption{\label{SpectralFormationBRLW} Left channel, spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 100 ms sliding Blackman window. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-SFBassRangeW} \caption{\label{SpectralFormationBRRW} Right channel, spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 100 ms sliding Blackman window. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-Spectrogram01ms} \caption{\label{HigResSpectrogram01msL} High resolution spectrograms from -10 ms to 40 ms, 1 ms Blackman window, 90 dB level range, left channel. The frequency range is from DC to the Nyquist frequency (22050 Hz) on a linear scale. The uncorrected system is on the top and the corrected system is on the bottom.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-Spectrogram01ms} \caption{\label{HigResSpectrogram01msR} High resolution spectrograms from -10 ms to 40 ms, 1 ms Blackman window, 90 dB level range, right channel. The frequency range is from DC to the Nyquist frequency (22050 Hz) on a linear scale. The uncorrected system is on the top and the corrected system is on the bottom.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-Spectrogram20ms} \caption{\label{HigResSpectrogram20msL} High resolution spectrograms from -100 ms to 400 ms, 20 ms Blackman window, 90 dB level range, left channel. The frequency range is from DC to the Nyquist frequency (22050 Hz) on a linear scale. The uncorrected system is on the top and the corrected system is on the bottom.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-Spectrogram20ms} \caption{\label{HigResSpectrogram20msR} High resolution spectrograms from -100 ms to 400 ms, 20 ms Blackman window, 90 dB level range, right channel. The frequency range is from DC to the Nyquist frequency (22050 Hz) on a linear scale. The uncorrected system is on the top and the corrected system is on the bottom.} \end{center} \end{figure} \clearpage \subsection{Wavelet cycle-octave analysis} \label{WaveletAnalysis} The wavelet analysis is a different method for performing a time-frequency analysis or, to be precise, a time-scale analysis. For certain kind of wavelets the scale axis could be mapped to a frequency scale, allowing for the usual time-frequency interpretation of the time-scale plots. Wavelets have the advantage of being easier to map to a logarithmic frequency scale. To further help the correct interpretation of the graphs the time scale is also stretched, depending on the frequency, so that the time scale is expressed in cycles of the sine wave of the corresponding frequency. The end result is a graph that provides a tiling of the time-frequency plane which is visually quite close to the kind of time-frequency analysis performed by our auditory system. The graphs are classical cycle-octave scalograms based on the Morlet wavelet, tuned for different tradeoffs between time and frequency resolution. % Morlet cycle-octave scalogram, alta risoluzione \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramHTRENVSD} \caption{\label{MorletScalogramHTRENVSDL} Left channel, Morlet cycle-octave scalogram envelope, high time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramHTRENVSD} \caption{\label{MorletScalogramHTRENVSDR} Right channel, Morlet cycle-octave scalogram envelope, high time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramHTRENVSF} \caption{\label{MorletScalogramHTRENVSFL} Left channel, Morlet cycle-octave scalogram envelope, high time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramHTRENVSF} \caption{\label{MorletScalogramHTRENVSFR} Right channel, Morlet cycle-octave scalogram envelope, high time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramHTRENVMap} \caption{\label{MorletScalogramHTRENVMapL} Left channel, Morlet cycle-octave scalogram envelope, high time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramHTRENVMap} \caption{\label{MorletScalogramHTRENVMapR} Right channel, Morlet cycle-octave scalogram envelope, high time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramHTRETCSD} \caption{\label{MorletScalogramHTRETCSDL} Left channel, Morlet cycle-octave scalogram ETC, high time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramHTRETCSD} \caption{\label{MorletScalogramHTRETCSDR} Right channel, Morlet cycle-octave scalogram ETC, high time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramHTRETCSF} \caption{\label{MorletScalogramHTRETCSFL} Left channel, Morlet cycle-octave scalogram ETC, high time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramHTRETCSF} \caption{\label{MorletScalogramHTRETCSFR} Right channel, Morlet cycle-octave scalogram ETC, high time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramHTRETCMap} \caption{\label{MorletScalogramHTRETCMapL} Left channel, Morlet cycle-octave scalogram ETC, high time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramHTRETCMap} \caption{\label{MorletScalogramHTRETCMapR} Right channel, Morlet cycle-octave scalogram ETC, high time resolution, colored map. } \end{center} \end{figure} % Morlet cycle-octave scalogram, media risoluzione \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramMTRENVSD} \caption{\label{MorletScalogramMTRENVSDL} Left channel, Morlet cycle-octave scalogram envelope, medium time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramMTRENVSD} \caption{\label{MorletScalogramMTRENVSDR} Right channel, Morlet cycle-octave scalogram envelope, medium time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramMTRENVSF} \caption{\label{MorletScalogramMTRENVSFL} Left channel, Morlet cycle-octave scalogram envelope, medium time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramMTRENVSF} \caption{\label{MorletScalogramMTRENVSFR} Right channel, Morlet cycle-octave scalogram envelope, medium time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramMTRENVMap} \caption{\label{MorletScalogramMTRENVMapL} Left channel, Morlet cycle-octave scalogram envelope, medium time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramMTRENVMap} \caption{\label{MorletScalogramMTRENVMapR} Right channel, Morlet cycle-octave scalogram envelope, medium time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramMTRETCSD} \caption{\label{MorletScalogramMTRETCSDL} Left channel, Morlet cycle-octave scalogram ETC, medium time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramMTRETCSD} \caption{\label{MorletScalogramMTRETCSDR} Right channel, Morlet cycle-octave scalogram ETC, medium time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramMTRETCSF} \caption{\label{MorletScalogramMTRETCSFL} Left channel, Morlet cycle-octave scalogram ETC, medium time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramMTRETCSF} \caption{\label{MorletScalogramMTRETCSFR} Right channel, Morlet cycle-octave scalogram ETC, medium time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-L-MorletScalogramMTRETCMap} \caption{\label{MorletScalogramMTRETCMapL} Left channel, Morlet cycle-octave scalogram ETC, medium time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-R-MorletScalogramMTRETCMap} \caption{\label{MorletScalogramMTRETCMapR} Right channel, Morlet cycle-octave scalogram ETC, medium time resolution, colored map. } \end{center} \end{figure} \clearpage \subsection{Baseline} \label{SampleResultsBaseline} The following series of graphs show the comparison between a Dirac delta and the corrected left channel. The Dirac delta is the mathematical representation of a ``perfect'' system i.e. a system which outputs a perfect copy of its input. Looking at these graphs it is possible to see both what is left uncorrected by DRC and what a ``perfect'' system looks like on this kind of graphs. The graphs are presented in the same order of the previous graphs. \subsubsection{Baseline time response} \label{BaselineTimeResponse} \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IRStepResponse} \caption{\label{BaselineStepResponseFullRange} Step response} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IRFullRange} \caption{\label{BaselineImpulseResponseFullRange} Full range impulse response.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IRFullRangeEnvelope} \caption{\label{BaselineEnvelopeFullRange} Full range impulse response envelope.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IRFullRangeETC} \caption{\label{BaselineETCFullRange}Full range time-energy response.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IR2kHzBrickwall} \caption{\label{BaselineImpulseResponse2kHzBrickwall} Impulse response after brickwall filtering at 2 kHz.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IR2kHzBrickwallEnvelope} \caption{\label{BaselineEnvelope2kHzBrickwall} Impulse response envelope after brickwall filtering at 2 kHz.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IR2kHzBrickwallETC} \caption{\label{BaselineETC2kHzBrickwall} Time-energy response after brickwall filtering at 2 kHz.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IR200HzBrickwall} \caption{\label{BaselineImpulseResponse200HzBrickwall} Impulse response after brickwall filtering at 200 Hz.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IR200HzBrickwallEnvelope} \caption{\label{BaselineEnvelope200HzBrickwall} Impulse response envelope after brickwall filtering at 200 Hz.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-IR200HzBrickwallETC} \caption{\label{BaselineETC200HzBrickwall} Time-energy response after brickwall filtering at 200 Hz.} \end{center} \end{figure} \clearpage \subsubsection{Baseline frequency response} \label{BaselineFrequencyResponse} \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRUnsmoothed1ms} \caption{\label{BaselineMagnitudeUnsmoothed1ms} Unsmoothed frequency response magnitude, 1 ms Blackman window.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRUnsmoothed5ms} \caption{\label{BaselineMagnitudeUnsmoothed5ms} Unsmoothed frequency response magnitude, 5 ms Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRUnsmoothed200ms} \caption{\label{BaselineMagnitudeUnsmoothed200ms} Unsmoothed frequency response magnitude, bass range, 200 ms Blackman window.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRFDWSmoothed} \caption{\label{BaselineFDWSmoothedNormal} Frequency response magnitude smoothed using a frequency dependent windowing with windowing settings close to those used by the normal.drc sample configuration file.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRFDWSmoothed-1-6} \caption{\label{BaselineMagnitudeFDWSmoothed16Oct} Frequency response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/6 of octave smoothing.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRFDWSmoothed-1-3} \caption{\label{BaselineMagnitudeFDWSmoothed13Oct} Frequency response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/3 of octave smoothing.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRBarkSmoothed} \caption{\label{BaselineMagnitudeBarkSmoothed} Frequency response magnitude smoothed over the Bark psychoacoustic scale with many different Blackman windows applied.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MRERBSmoothed} \caption{\label{BaselineMagnitudeERBSmoothed} Frequency response magnitude smoothed over the Bark psychoacoustic scale with many different Blackman windows applied.} \end{center} \end{figure} \clearpage \subsubsection{Baseline phase response} \label{BaselinePhaseResponse} \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-PRUnsmoothed1ms} \caption{\label{BaselinePhaseResponse1} Unsmoothed phase response, 1 ms Blackman window.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-PRUnsmoothed5ms} \caption{\label{BaselinePhaseResponse5} Unsmoothed phase response, 5 ms Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-PRUnsmoothed200ms} \caption{\label{BaselinePhaseResponse200} Unsmoothed phase response, 200 ms Blackman window.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-PRFDWSmoothed} \caption{\label{BaselinePhaseFDWSmoothedNormal} Phase response smoothed using a frequency dependent windowing with windowing settings close to those used by the normal.drc sample configuration file.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-PRFDWSmoothed-1-6} \caption{\label{BaselinePhaseFDWSmoothed16Oct} Phase response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/6 of octave smoothing.} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-PRFDWSmoothed-1-3} \caption{\label{BaselinePhaseFDWSmoothed13Oct} Phase response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/3 of octave smoothing.} \end{center} \end{figure} \clearpage \subsubsection{Baseline time-frequency analysis} \label{BaselineTimeFrequencyAnalysis} \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SDHighRange} \caption{\label{BaselineSpectralDecayHR} Left channel, spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SFHighRange} \caption{\label{BaselineSpectralFormationHR} Left channel, spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SDMidRange} \caption{\label{BaselineSpectralDecayMR} Left channel, spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SFMidRange} \caption{\label{BaselineSpectralFormationMR} Left channel, spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SDBassRange} \caption{\label{BaselineSpectralDecayBR} Left channel, spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 50 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SFBassRange} \caption{\label{BaselineSpectralFormationBR} Left channel, spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 50 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SDHighRangeW} \caption{\label{BaselineSpectralDecayHRW} Left channel, spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SFHighRangeW} \caption{\label{BaselineSpectralFormationHRW} Left channel, spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SDMidRangeW} \caption{\label{BaselineSpectralDecayMRW} Left channel, spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SFMidRangeW} \caption{\label{BaselineSpectralFormationMRW} Left channel, spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SDBassRangeW} \caption{\label{BaselineSpectralDecayBRW} Left channel, spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 50 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-SFBassRangeW} \caption{\label{BaselineSpectralFormationBRW} Left channel, spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 100 ms sliding Blackman window.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-Spectrogram01ms} \caption{\label{BaselineHigResSpectrogram01ms} High resolution spectrograms from -10 ms to 40 ms, 1 ms Blackman window, 90 dB level range, left channel. The frequency range is from DC to Nyquist (22050 Hz) on a linear scale.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-Spectrogram20ms} \caption{\label{BaselineHigResSpectrogram20ms} High resolution spectrograms from -100 ms to 400 ms, 20 ms Blackman window, 90 dB level range, left channel. The frequency range is from DC to Nyquist (22050 Hz) on a linear scale.} \end{center} \end{figure} \clearpage \subsubsection{Baseline wavelet cycle-octave analysis} \label{BaselineWaveletAnalysis} % Morlet cycle-octave scalogram, alta risoluzione \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramHTRENVSD} \caption{\label{MorletScalogramHTRENVSDB} Baseline, Morlet cycle-octave scalogram envelope, high time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramHTRENVSF} \caption{\label{MorletScalogramHTRENVSFB} Baseline, Morlet cycle-octave scalogram envelope, high time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramHTRENVMap} \caption{\label{MorletScalogramHTRENVMapB} Baseline, Morlet cycle-octave scalogram envelope, high time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramHTRETCSD} \caption{\label{MorletScalogramHTRETCSDB} Baseline, Morlet cycle-octave scalogram ETC, high time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramHTRETCSF} \caption{\label{MorletScalogramHTRETCSFB} Baseline, Morlet cycle-octave scalogram ETC, high time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramHTRETCMap} \caption{\label{MorletScalogramHTRETCMapB} Baseline, Morlet cycle-octave scalogram ETC, high time resolution, colored map. } \end{center} \end{figure} % Morlet cycle-octave scalogram, media risoluzione \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramMTRENVSD} \caption{\label{MorletScalogramMTRENVSDB} Baseline, Morlet cycle-octave scalogram envelope, medium time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramMTRENVSF} \caption{\label{MorletScalogramMTRENVSFB} Baseline, Morlet cycle-octave scalogram envelope, medium time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramMTRENVMap} \caption{\label{MorletScalogramMTRENVMapB} Baseline, Morlet cycle-octave scalogram envelope, medium time resolution, colored map. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramMTRETCSD} \caption{\label{MorletScalogramMTRETCSDB} Baseline, Morlet cycle-octave scalogram ETC, medium time resolution, spectral decay. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramMTRETCSF} \caption{\label{MorletScalogramMTRETCSFB} Baseline, Morlet cycle-octave scalogram ETC, medium time resolution, spectral formation. } \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{figures/SR-B-MorletScalogramMTRETCMap} \caption{\label{MorletScalogramMTRETCMapB} Baseline, Morlet cycle-octave scalogram ETC, medium time resolution, colored map. } \end{center} \end{figure} \end{document} drc-3.2.2/source/doc/figures/0000755000076400001450000000000013165107356014771 5ustar denisitadmdrc-3.2.2/source/doc/drc-graphs.tex0000644000076400001450000003710111670332116016074 0ustar denisitadm% DRC: Digital Room Correction % Graph packaging LaTeX script % % Copyright (C) 2005 Michele Spinolo % Copyright (C) 2005 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: % % michele.spinolo@tin.it \documentclass[a4paper,titlepage]{article} \usepackage{url} \usepackage{graphicx} \usepackage{tocloft} \usepackage[colorlinks=true,pdfstartview=FitH,bookmarks=true, bookmarksnumbered,pdfpagemode=None,plainpages=false, pdfpagelabels,a4paper,linktocpage]{hyperref} % Figure names prefix \newcommand{\pctprefix}{T} % Figures width \newcommand{\pctwidth}{1.0} % Replace with your title and name \title{DRC Graphs} \author{Michele Spinolo} \begin{document} \pagenumbering{roman} \begin{titlepage} \maketitle\thispagestyle{empty} \end{titlepage} \pagenumbering{arabic} \clearpage \listoffigures %IR Full range \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IRStepResponse} \caption{Full range step response.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IRFullRange} \caption{Full range impulse response.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IRFullRangeEnvelope} \caption{Full range impulse response envelope.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IRFullRangeETC} \caption{Full range time-energy response (impulse response envelope plotted with a logarithmic magnitude scale).} \end{center} \end{minipage} \end{figure} \clearpage %IR 2kHz Brickwall \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IR2kHzBrickwall} \caption{Impulse response brickwall filtered at 2 kHz.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IR2kHzBrickwallEnvelope} \caption{Impulse response envelope brickwall filtered at 2 kHz.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IR2kHzBrickwallETC} \caption{Time-energy response (impulse response envelope plotted with a logarithmic magnitude scale) brickwall filtered at 2 kHz.} \end{center} \end{minipage} %IR 200Hz Brickwall \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IR200HzBrickwall} \caption{Impulse response brickwall filtered at 200 Hz.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IR200HzBrickwallEnvelope} \caption{Impulse response envelope brickwall filtered at 200 Hz.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-IR200HzBrickwallETC} \caption{Time-energy response (impulse response envelope plotted with a logarithmic magnitude scale) brickwall filtered at 200 Hz.} \end{center} \end{minipage} \end{figure} \clearpage %Magnitude response \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRUnsmoothed1ms} \caption{Unsmoothed frequency response magnitude, 1 ms Blackman window. These graphs show the frequency response of the early direct sound.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRUnsmoothed5ms} \caption{Unsmoothed frequency response magnitude, 5 ms Blackman window. These graphs show the frequency response of the direct sound.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRUnsmoothed200ms} \caption{Unsmoothed frequency response magnitude, bass range, 200 ms Blackman window. These graphs show the frequency response of the bass range over a 200 ms time window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRFDWSmoothed} \caption{Frequency response magnitude smoothed using a frequency dependent windowing with windowing settings close to those used by the normal.drc sample configuration file.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRFDWSmoothed-1-6} \caption{Frequency response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/6 of octave smoothing.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRFDWSmoothed-1-3} \caption{Frequency response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/3 of octave smoothing.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRBarkSmoothed} \caption{Frequency response magnitude smoothed over the Bark psychoacoustic scale with many different Blackman windows applied.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MRERBSmoothed} \caption{Frequency response magnitude smoothed over the ERB psychoacoustic scale with many different Blackman windows applied.} \end{center} \end{minipage} \end{figure} \clearpage %Phase response \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-PRUnsmoothed1ms} \caption{Unsmoothed phase response, 1 ms Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-PRUnsmoothed5ms} \caption{Unsmoothed phase response, 5 ms Blackman window.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-PRUnsmoothed200ms} \caption{Unsmoothed phase response, bass range, 200 ms Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-PRFDWSmoothed} \caption{Phase response smoothed using a frequency dependent windowing with windowing settings close to those used by the normal.drc sample configuration file.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-PRFDWSmoothed-1-6} \caption{Phase response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/6 of octave smoothing.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-PRFDWSmoothed-1-3} \caption{Phase response magnitude smoothed using a frequency dependent windowing providing a frequency resolution close to 1/3 of octave smoothing.} \end{center} \end{minipage} \end{figure} \clearpage % Time-frequency analysis \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SDHighRange} \caption{Spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SFHighRange} \caption{Spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 0.5 ms sliding Blackman window.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SDMidRange} \caption{Spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SFMidRange} \caption{Spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 5 ms sliding Blackman window.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SDBassRange} \caption{Spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 50 ms sliding Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SFBassRange} \caption{Spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 50 ms sliding Blackman window.} \end{center} \end{minipage} \end{figure} % Time-frequency analysis, wider windows \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SDHighRangeW} \caption{Spectral decay, high range. Spectral decay from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SFHighRangeW} \caption{Spectral formation, high range. Spectral formation from 2 kHz to 20 kHz with a 1.0 ms sliding Blackman window.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SDMidRangeW} \caption{Spectral decay, mid range. Spectral decay from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SFMidRangeW} \caption{Spectral formation, mid range. Spectral formation from 200 Hz to 2000 Hz with a 10 ms sliding Blackman window.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SDBassRangeW} \caption{Spectral decay, bass range. Spectral decay from 20 Hz to 200 Hz with a 100 ms sliding Blackman window.} \end{center} \end{minipage} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-SFBassRangeW} \caption{Spectral formation, bass range. Spectral formation from 20 Hz to 200 Hz with a 100 ms sliding Blackman window.} \end{center} \end{minipage} \end{figure} \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-Spectrogram01ms} \caption{High resolution spectrograms from -10 ms to 40 ms, 1 ms Blackman window, 60 dB level range. The frequency range is from DC to Nyquist (22050 Hz) on a linear scale.} \end{center} \end{minipage} \end{figure} \begin{figure} \begin{minipage}{\textwidth} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-Spectrogram20ms} \caption{High resolution spectrograms from -100 ms to 400 ms, 20 ms Blackman window, 60 dB level range. The frequency range is from DC to Nyquist (22050 Hz) on a linear scale.} \end{center} \end{minipage} \end{figure} \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramHTRENVSD} \caption{Morlet cycle-octave scalogram envelope, high time resolution, spectral decay.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramHTRENVSF} \caption{Morlet cycle-octave scalogram envelope, high time resolution, spectral formation.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramHTRENVMap} \caption{Morlet cycle-octave scalogram envelope, high time resolution, colored map.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramHTRETCSD} \caption{Morlet cycle-octave scalogram ETC, high time resolution, spectral decay.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramHTRETCSF} \caption{Morlet cycle-octave scalogram ETC, high time resolution, spectral formation.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramHTRETCMap} \caption{Morlet cycle-octave scalogram ETC, high time resolution, colored map.} \end{center} \end{figure} \clearpage \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramMTRENVSD} \caption{Morlet cycle-octave scalogram envelope, medium time resolution, spectral decay.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramMTRENVSF} \caption{Morlet cycle-octave scalogram envelope, medium time resolution, spectral formation.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramMTRENVMap} \caption{Morlet cycle-octave scalogram envelope, medium time resolution, colored map.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramMTRETCSD} \caption{Morlet cycle-octave scalogram ETC, medium time resolution, spectral decay.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramMTRETCSF} \caption{Morlet cycle-octave scalogram ETC, medium time resolution, spectral formation.} \end{center} \end{figure} \begin{figure} \begin{center} \includegraphics[width=\pctwidth\textwidth,keepaspectratio]{\pctprefix-MorletScalogramMTRETCMap} \caption{Morlet cycle-octave scalogram ETC, medium time resolution, colored map.} \end{center} \end{figure} \end{document} drc-3.2.2/source/doc/genpdf0000644000076400001450000000053413163167047014516 0ustar denisitadm#!/bin/sh # Create the pdf version of all eps files for file in figures/*.eps do pdffile=$(basename "$file" .eps) echo "$file" '->' "${pdffile}.pdf" epstopdf -nogs "$file" | ps2pdf -dAutoFilterColorImages=false -dColorImageFilter=/FlateEncode -dPDFSETTINGS=/prepress -dColorImageResolution=600 -dGrayImageResolution=600 - "${pdffile}.pdf" done drc-3.2.2/source/doc/fsource/0000755000076400001450000000000013165107356014773 5ustar denisitadmdrc-3.2.2/source/doc/drc.sty0000644000076400001450000000050213163201322014615 0ustar denisitadmdrc-3.2.2/source/cmdline.h0000644000076400001450000000512413162156312014337 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2004 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@neomerica.it ****************************************************************************/ /* Command line parsing utilities */ #ifndef CmdLine_h #define CmdLine_h #include "drc.h" #include "cfgparse.h" #include "boolean.h" #include /* Struttura gestione parametri */ typedef union { char * StrParm; int IntParm; DRCFloat FltParm; } ParameterType; /* Struttura gestione opzioni */ typedef struct { int OptCount; struct option * Options; ParameterType * Parms; Boolean * ParmSet; } CmdLineType; #ifdef __cplusplus extern "C" { #endif /* Registra le impostazioni per la command line a partire da una definizione ParseCfg. Torna una struttura opaque utilizzata per il recupero dei parametri dalla linea di comando. */ CmdLineType * RegisterCmdLine(const CfgParameter * CfgParmsDef); /* Effettua il processing della command line */ int GetCmdLine(const int argc, char * const * argv, const CfgParameter * CfgParmsDef, CmdLineType * OptData, char ** CfgFileName); /* Sovrascrive i parametri della definizione ParseCfg CfgParmsDef con i parametri recuperati dalla linea di comando e registrati nella in OptData. */ void CopyCmdLineParms(const CmdLineType * OptData,CfgParameter * CfgParmsDef); /* Visualizza le opzioni disponibili a linea di comando */ void ShowCmdLine(const CfgParameter * CfgParmsDef); /* Libera la memoria occupata per la gestione della command line */ void FreeCmdLine(CmdLineType * OptData, const CfgParameter * CfgParmsDef); /* Libera la memoria di una strttura di configurazione */ void FreeCfgParameters(CfgParameter * CfgParmsDef); #ifdef __cplusplus } #endif #endif drc-3.2.2/source/contrib/0000755000076400001450000000000013165107356014220 5ustar denisitadmdrc-3.2.2/source/contrib/readme.txt0000644000076400001450000000007710332166114016210 0ustar denisitadmThis folder contains some files contributed by various authors.drc-3.2.2/source/contrib/NSIS Installer Script/0000755000076400001450000000000013165107356020137 5ustar denisitadmdrc-3.2.2/source/contrib/NSIS Installer Script/readme.txt0000644000076400001450000000023510332164256022130 0ustar denisitadmThis is a NSIS (Nullsoft Scriptable Install System) script provided by Ed Wildgoose. For more informations about NSIS see: http://nsis.sourceforge.net/drc-3.2.2/source/contrib/NSIS Installer Script/drc-installer.nsi0000644000076400001450000001310510332343574023412 0ustar denisitadm; Script generated by the HM NIS Edit Script Wizard. ; HM NIS Edit Wizard helper defines !define PRODUCT_NAME "DRC" !define PRODUCT_VERSION "2.6.1" !define PRODUCT_PUBLISHER "Denis Sbragion" !define PRODUCT_WEB_SITE "http://drc-fir.sourceforge.net" !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\drc.exe" !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" !define PRODUCT_UNINST_ROOT_KEY "HKLM" SetCompressor lzma ; MUI 1.67 compatible ------ !include "MUI.nsh" ; MUI Settings !define MUI_ABORTWARNING !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico" !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" ; Language Selection Dialog Settings !define MUI_LANGDLL_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}" !define MUI_LANGDLL_REGISTRY_KEY "${PRODUCT_UNINST_KEY}" !define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language" ; Welcome page !insertmacro MUI_PAGE_WELCOME ; License page !insertmacro MUI_PAGE_LICENSE "COPYING" ; Directory page !insertmacro MUI_PAGE_DIRECTORY ; Instfiles page !insertmacro MUI_PAGE_INSTFILES ; Finish page !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\drc.txt" !insertmacro MUI_PAGE_FINISH ; Uninstaller pages !insertmacro MUI_UNPAGE_INSTFILES ; Language files !insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "Italian" ; Reserve files !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS ; MUI end ------ Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" OutFile "Setup.exe" InstallDir "$PROGRAMFILES\DRC" InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "" ShowInstDetails show ShowUnInstDetails show Function .onInit !insertmacro MUI_LANGDLL_DISPLAY FunctionEnd Section "MainSection" SEC01 SetOutPath "$INSTDIR" SetOverwrite ifnewer File "sample\drc.exe" File "sample\glsweep.exe" File "sample\lsconv.exe" File "doc\text\drc.txt" File "readme.txt" File "COPYING" SetOutPath "$INSTDIR\config" SetOverwrite ifnewer File "source\config\*" SetOutPath "$INSTDIR\target" SetOverwrite ifnewer File "source\target\*" SetOutPath "$INSTDIR\mic" SetOverwrite ifnewer File "source\mic\*" SetOutPath "$INSTDIR\impulse" SetOverwrite ifnewer File "sample\rs.pcm" SetOutPath "$INSTDIR\filter" CreateDirectory "$SMPROGRAMS\DRC" CreateShortCut "$SMPROGRAMS\DRC\DRC.lnk" "$INSTDIR\drc.txt" SectionEnd Section -AdditionalIcons WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}" CreateShortCut "$SMPROGRAMS\DRC\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url" CreateShortCut "$SMPROGRAMS\DRC\Uninstall.lnk" "$INSTDIR\uninst.exe" SectionEnd Section -Post WriteUninstaller "$INSTDIR\uninst.exe" WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\drc.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\drc.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" SectionEnd Function un.onUninstSuccess HideWindow MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer." FunctionEnd Function un.onInit !insertmacro MUI_UNGETLANGUAGE MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2 Abort FunctionEnd Section Uninstall Delete "$INSTDIR\${PRODUCT_NAME}.url" Delete "$INSTDIR\uninst.exe" Delete "$INSTDIR\lsconv.exe" Delete "$INSTDIR\glsweep.exe" Delete "$INSTDIR\drc.exe" Delete "$INSTDIR\readme.txt" Delete "$INSTDIR\drc.txt" Delete "$INSTDIR\COPYING" Delete "$INSTDIR\impulse\rs.pcm" Delete "$INSTDIR\config\erb.drc" Delete "$INSTDIR\config\minimal.drc" Delete "$INSTDIR\config\soft.drc" Delete "$INSTDIR\config\normal.drc" Delete "$INSTDIR\config\strong.drc" Delete "$INSTDIR\config\insane.drc" Delete "$INSTDIR\config\extreme.drc" Delete "$INSTDIR\config\optimized.drc" Delete "$INSTDIR\mic\wm-61a.txt" Delete "$INSTDIR\mic\wm-60a.txt" Delete "$INSTDIR\mic\ecm8000.txt" Delete "$INSTDIR\target\flat.txt" Delete "$INSTDIR\target\subultra.txt" Delete "$INSTDIR\target\ultra.txt" Delete "$INSTDIR\target\bk-spline.txt" Delete "$INSTDIR\target\bk-sub-spline.txt" Delete "$INSTDIR\target\bk-sub.txt" Delete "$INSTDIR\target\bk.txt" Delete "$INSTDIR\target\bk-2-spline.txt" Delete "$INSTDIR\target\bk-2-sub-spline.txt" Delete "$INSTDIR\target\bk-2-sub.txt" Delete "$INSTDIR\target\bk-2.txt" Delete "$INSTDIR\target\bk-3-spline.txt" Delete "$INSTDIR\target\bk-3-sub-spline.txt" Delete "$INSTDIR\target\bk-3-sub.txt" Delete "$INSTDIR\target\bk-3-subultra-spline.txt" Delete "$INSTDIR\target\bk-3.txt" Delete "$SMPROGRAMS\DRC\Uninstall.lnk" Delete "$SMPROGRAMS\DRC\Website.lnk" Delete "$SMPROGRAMS\DRC\DRC.lnk" RMDir "$SMPROGRAMS\DRC" RMDir "$INSTDIR\impulse" RMDir "$INSTDIR\config" RMDir "$INSTDIR\mic" RMDir "$INSTDIR\target" RMDir "$INSTDIR" DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" SetAutoClose true SectionEnddrc-3.2.2/source/contrib/MeasureJack/0000755000076400001450000000000013165107356016412 5ustar denisitadmdrc-3.2.2/source/contrib/MeasureJack/readme.txt0000644000076400001450000000021210332213624020370 0ustar denisitadmThe measurejack script is used to perform impulse response measurements. Please refere to the DRC documentation for further informations.drc-3.2.2/source/contrib/MeasureJack/measurejack0000644000076400001450000000757411622465007020640 0ustar denisitadm#!/bin/sh # Automatic measuring script # Copyright (C) 2002-2005 Denis Sbragion # Copyright (C) 2005 Chris Birkinshaw # This program may be freely redistributed under the terms of # the GNU GPL and is provided to you as is, without any warranty # of any kind. Please read the file "COPYING" for details. # Useful programs ECHO="echo" RM="rm" GLSWEEP="glsweep" SOX="sox" LSCONV="lsconv" APLAY="aplay" ARECORD="arecord" SYNC="sync" SLEEP="sleep" ALSAPLAYER=alsaplayer # Default parameters TMP="/tmp" AMPLITUDE="0.5" LEADIN="0.05" LEADOUT="0.005" MINGAIN="0.1" DLSTART="0.9" $ECHO $ECHO "Automatic measuring script." $ECHO "Copyright (C) 2002-2005 Denis Sbragion" $ECHO "Copyright (C) 2005 Chris Birkinshaw" $ECHO $ECHO "This program may be freely redistributed under the terms of" $ECHO "the GNU GPL and is provided to you as is, without any warranty" $ECHO "of any kind. Please read the file "COPYING" for details." $ECHO # Command line check if [[ $# != 9 && $# != 10 ]]; then $ECHO "Usage:" $ECHO " measure bits rate startf endf lslen lssil indev outdev impfile [sweepfile]" $ECHO $ECHO " bits: measuring bits (16 or 24)" $ECHO " rate: sample rate" $ECHO " startf: sweep start frequency in Hz" $ECHO " endf: sweep end frequency in Hz" $ECHO " lslen: log sweep length in seconds" $ECHO " lssil: log sweep silence length in seconds" $ECHO " indev: ALSA input device" $ECHO " outdev: JACK output device" $ECHO " impfile: impulse response output file" $ECHO " sweepfile: optional wav file name for the recorded sweep" $ECHO $ECHO "example: measurejack 16 44100 5 21000 45 2 plughw brutefir:input-0,brutefir:input-1 impulse.pcm" $ECHO $ECHO "Tip: jackd must not be using the recording channels of your soundcard, i.e. launch with the -P option" $ECHO exit 0 fi # Get command line parameters BITS="$1" RATE="$2" STARTF="$3" ENDF="$4" LSLEN="$5" LSSIL="$6" INDEV="$7" OUTDEV="$8" IMPFILE="$9" SWEEPFILE="${10}" # Check bits to use if [ "$BITS" == "24" ]; then SOXFMT="-s4" ARECORDFMT="S32_LE" else SOXFMT="-s2" ARECORDFMT="S16_LE" fi # Generate the log sweep $GLSWEEP $RATE $AMPLITUDE $STARTF $ENDF $LSLEN $LSSIL $LEADIN $LEADOUT ${TMP}/msrawsweep.pcm ${TMP}/msinverse.pcm # Convert to WAV file $ECHO "Converting sweep to play format..." $SOX -t raw -r $RATE -c 1 -f4 ${TMP}/msrawsweep.pcm -t wav -c 2 $SOXFMT ${TMP}/msplaysweep.wav $RM ${TMP}/msrawsweep.pcm # Filesystem sync $ECHO "Waiting 5 seconds for filesystem sync..." $SYNC $SLEEP 5 # Record the sweep $ECHO "Sweep recording." $ECHO "Measuring channel: left. Reference channel: right." $SLEEP 1 RLEN=$(( $LSLEN + $LSSIL * 2 )) $ALSAPLAYER -o jack -d "$OUTDEV" -i text ${TMP}/msplaysweep.wav & $ARECORD -D $INDEV -t wav -r $RATE -f $ARECORDFMT -c 2 -d $RLEN ${TMP}/msrecsweep.wav # Remove the play sweep file $RM ${TMP}/msplaysweep.wav # Convert sweep file $ECHO "Sweep file extraction (left channel)..." $SOX ${TMP}/msrecsweep.wav -t raw -r $RATE -f4 -c 1 ${TMP}/mssweep.pcm mixer -l # Extract reference file $ECHO "Reference file extraction (right channel)..." $SOX ${TMP}/msrecsweep.wav -t raw -r $RATE -f4 -c 1 ${TMP}/msrefer.pcm mixer -r # Move or remove the recorded file if [ "$SWEEPFILE" != "" ]; then $ECHO "Copying sweepfile to ${SWEEPFILE}..." $MV ${TMP}/msrecsweep.wav "$SWEEPFILE" else $RM ${TMP}/msrecsweep.wav fi # Print stats $ECHO $ECHO "Measuring channel (left) stats..." $ECHO $SOX -t raw -r $RATE -f4 -c 1 ${TMP}/mssweep.pcm -n stat $ECHO $ECHO "Reference channel (right) stats..." $ECHO $SOX -t raw -r $RATE -f4 -c 1 ${TMP}/msrefer.pcm -n stat # Extract the impulse response $LSCONV ${TMP}/mssweep.pcm ${TMP}/msinverse.pcm $IMPFILE ${TMP}/msrefer.pcm $MINGAIN $DLSTART # Impulse response stats $ECHO $ECHO "Impulse response stats..." $ECHO $SOX -t raw -r $RATE -f4 -c1 $IMPFILE -n stat $ECHO "Temporary file cleanup..." $RM ${TMP}/mssweep.pcm $RM ${TMP}/msrefer.pcm $RM ${TMP}/msinverse.pcm $ECHO "Impulse response measurement completed." drc-3.2.2/source/contrib/Measure/0000755000076400001450000000000013165107356015621 5ustar denisitadmdrc-3.2.2/source/contrib/Measure/measure0000644000076400001450000000735111622465441017211 0ustar denisitadm#!/bin/bash # Automatic measuring script # Copyright (C) 2002-2005 Denis Sbragion # This program may be freely redistributed under the terms of # the GNU GPL and is provided to you as is, without any warranty # of any kind. Please read the file "COPYING" for details. # Useful programs ECHO="echo" RM="rm" MV="mv" GLSWEEP="glsweep" SOX="sox" LSCONV="lsconv" APLAY="aplay" ARECORD="arecord" SYNC="sync" SLEEP="sleep" # Default parameters TMP="/tmp" AMPLITUDE="0.5" LEADIN="0.05" LEADOUT="0.005" MINGAIN="0.1" DLSTART="0.9" $ECHO $ECHO "Automatic measuring script." $ECHO "Copyright (C) 2002-2005 Denis Sbragion" $ECHO $ECHO "This program may be freely redistributed under the terms of" $ECHO "the GNU GPL and is provided to you as is, without any warranty" $ECHO "of any kind. Please read the file "COPYING" for details." $ECHO # Command line check if [[ $# != 9 && $# != 10 ]]; then $ECHO "Usage:" $ECHO " measure bits rate startf endf lslen lssil indev outdev impfile [sweepfile]" $ECHO $ECHO " bits: measuring bits (16 or 24)" $ECHO " rate: sample rate" $ECHO " startf: sweep start frequency in Hz" $ECHO " endf: sweep end frequency in Hz" $ECHO " lslen: log sweep length in seconds" $ECHO " lssil: log sweep silence length in seconds" $ECHO " indev: ALSA input device" $ECHO " outdev: ALSA output device" $ECHO " impfile: impulse response output file" $ECHO " sweepfile: optional wav file name for the recorded sweep" $ECHO $ECHO "example: measure 16 44100 5 21000 45 2 plughw plughw impulse.pcm" $ECHO exit 0 fi # Get command line parameters BITS="$1" RATE="$2" STARTF="$3" ENDF="$4" LSLEN="$5" LSSIL="$6" INDEV="$7" OUTDEV="$8" IMPFILE="$9" SWEEPFILE="${10}" # Check bits to use if [ "$BITS" == "24" ]; then SOXFMT="-e signed-integer -b 24" ARECORDFMT="S24_3LE" else SOXFMT="-e signed-integer -b 16" ARECORDFMT="S16_LE" fi # Generate the log sweep $GLSWEEP $RATE $AMPLITUDE $STARTF $ENDF $LSLEN $LSSIL $LEADIN $LEADOUT ${TMP}/msrawsweep.pcm ${TMP}/msinverse.pcm # Convert to WAV file $ECHO "Converting sweep to play format..." $SOX -t raw -r $RATE -c 1 -e float -b32 ${TMP}/msrawsweep.pcm -t wav -r $RATE -c 2 $SOXFMT ${TMP}/msplaysweep.wav $RM ${TMP}/msrawsweep.pcm # Filesystem sync $ECHO "Waiting 5 seconds for filesystem sync..." $SYNC $SLEEP 5 # Record the sweep $ECHO "Sweep recording." $ECHO "Measuring channel: left. Reference channel: right." $SLEEP 1 RLEN=$(( $LSLEN + $LSSIL * 2 )) $APLAY -D $OUTDEV ${TMP}/msplaysweep.wav & $ARECORD -D $INDEV -t wav -r $RATE -f $ARECORDFMT -c 2 -d $RLEN ${TMP}/msrecsweep.wav # Remove the play sweep file $RM ${TMP}/msplaysweep.wav # Convert sweep file $ECHO "Sweep file extraction (left channel)..." $SOX ${TMP}/msrecsweep.wav -t raw -r $RATE -e float -b 32 -c 1 ${TMP}/mssweep.pcm mixer -l # Extract reference file $ECHO "Reference file extraction (right channel)..." $SOX ${TMP}/msrecsweep.wav -t raw -r $RATE -e float -b 32 -c 1 ${TMP}/msrefer.pcm mixer -r # Move or remove the recorded file if [ "$SWEEPFILE" != "" ]; then $ECHO "Copying sweepfile to ${SWEEPFILE}..." $MV ${TMP}/msrecsweep.wav "$SWEEPFILE" else $RM ${TMP}/msrecsweep.wav fi # Print stats $ECHO $ECHO "Measuring channel (left) stats..." $ECHO $SOX -t raw -r $RATE -e float -b 32 -c 1 ${TMP}/mssweep.pcm -n stat $ECHO $ECHO "Reference channel (right) stats..." $ECHO $SOX -t raw -r $RATE -e float -b 32 -c 1 ${TMP}/msrefer.pcm -n stat # Extract the impulse response $LSCONV ${TMP}/mssweep.pcm ${TMP}/msinverse.pcm $IMPFILE ${TMP}/msrefer.pcm $MINGAIN $DLSTART # Impulse response stats $ECHO $ECHO "Impulse response stats..." $ECHO $SOX -t raw -r $RATE -e float -b 32 -c1 $IMPFILE -n stat $ECHO "Temporary file cleanup..." #$RM ${TMP}/mssweep.pcm #$RM ${TMP}/msrefer.pcm #$RM ${TMP}/msinverse.pcm $ECHO "Impulse response measurement completed." drc-3.2.2/source/contrib/Measure/readme.txt0000644000076400001450000000021210332213644017601 0ustar denisitadmThe measure script is used to perform impulse response measurements. Please refere to the DRC documentation for further informations.drc-3.2.2/source/fftsg.c0000644000076400001450000025726010350310446014036 0ustar denisitadm#include "fftsg.h" /* Fast Fourier/Cosine/Sine Transform dimension :one data length :power of 2 decimation :frequency radix :split-radix data :inplace table :use functions cdft: Complex Discrete Fourier Transform rdft: Real Discrete Fourier Transform ddct: Discrete Cosine Transform ddst: Discrete Sine Transform dfct: Cosine Transform of RDFT (Real Symmetric DFT) dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) function prototypes void cdft(int, int, double *, int *, double *); void rdft(int, int, double *, int *, double *); void ddct(int, int, double *, int *, double *); void ddst(int, int, double *, int *, double *); void dfct(int, double *, double *, int *, double *); void dfst(int, double *, double *, int *, double *); macro definitions USE_CDFT_PTHREADS : default=not defined CDFT_THREADS_BEGIN_N : must be >= 512, default=8192 CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536 USE_CDFT_WINTHREADS : default=not defined CDFT_THREADS_BEGIN_N : must be >= 512, default=32768 CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288 -------- Complex DFT (Discrete Fourier Transform) -------- [definition] X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k ip[0] = 0; // first time only cdft(2*n, 1, a, ip, w); ip[0] = 0; // first time only cdft(2*n, -1, a, ip, w); [parameters] 2*n :data length (int) n >= 1, n = power of 2 a[0...2*n-1] :input/output data (double *) input data a[2*j] = Re(x[j]), a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) strictly, length of ip >= 2+(1<<(int)(log(n+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n/2-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of cdft(2*n, -1, a, ip, w); is cdft(2*n, 1, a, ip, w); for (j = 0; j <= 2 * n - 1; j++) { a[j] *= 1.0 / n; } . -------- Real DFT / Inverse of Real DFT -------- [definition] RDFT R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k ip[0] = 0; // first time only rdft(n, 1, a, ip, w); ip[0] = 0; // first time only rdft(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[2*k] = R[k], 0<=k input data a[2*j] = R[j], 0<=j= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n/2-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of rdft(n, 1, a, ip, w); is rdft(n, -1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- [definition] IDCT (excluding scale) C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k ip[0] = 0; // first time only ddct(n, 1, a, ip, w); ip[0] = 0; // first time only ddct(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = C[k], 0<=k= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/4-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of ddct(n, -1, a, ip, w); is a[0] *= 0.5; ddct(n, 1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- DST (Discrete Sine Transform) / Inverse of DST -------- [definition] IDST (excluding scale) S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 ip[0] = 0; // first time only ddst(n, 1, a, ip, w); ip[0] = 0; // first time only ddst(n, -1, a, ip, w); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) input data a[j] = A[j], 0 output data a[k] = S[k], 0= 2+sqrt(n/2) strictly, length of ip >= 2+(1<<(int)(log(n/2+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/4-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of ddst(n, -1, a, ip, w); is a[0] *= 0.5; ddst(n, 1, a, ip, w); for (j = 0; j <= n - 1; j++) { a[j] *= 2.0 / n; } . -------- Cosine Transform of RDFT (Real Symmetric DFT) -------- [definition] C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n [usage] ip[0] = 0; // first time only dfct(n, a, t, ip, w); [parameters] n :data length - 1 (int) n >= 2, n = power of 2 a[0...n] :input/output data (double *) output data a[k] = C[k], 0<=k<=n t[0...n/2] :work area (double *) ip[0...*] :work area for bit reversal (int *) length of ip >= 2+sqrt(n/4) strictly, length of ip >= 2+(1<<(int)(log(n/4+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/8-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of a[0] *= 0.5; a[n] *= 0.5; dfct(n, a, t, ip, w); is a[0] *= 0.5; a[n] *= 0.5; dfct(n, a, t, ip, w); for (j = 0; j <= n; j++) { a[j] *= 2.0 / n; } . -------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- [definition] S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = S[k], 0= 2+sqrt(n/4) strictly, length of ip >= 2+(1<<(int)(log(n/4+0.5)/log(2))/2). ip[0],ip[1] are pointers of the cos/sin table. w[0...n*5/8-1] :cos/sin table (double *) w[],ip[] are initialized if ip[0] == 0. [remark] Inverse of dfst(n, a, t, ip, w); is dfst(n, a, t, ip, w); for (j = 1; j <= n - 1; j++) { a[j] *= 2.0 / n; } . Appendix : The cos/sin table is recalculated when the larger table required. w[] and ip[] are compatible with all routines. */ void cdft(int n, int isgn, DRCFloat *a, int *ip, DRCFloat *w) { void makewt(int nw, int *ip, DRCFloat *w); void cftfsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void cftbsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); int nw; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } if (isgn >= 0) { cftfsub(n, a, ip, nw, w); } else { cftbsub(n, a, ip, nw, w); } } void rdft(int n, int isgn, DRCFloat *a, int *ip, DRCFloat *w) { void makewt(int nw, int *ip, DRCFloat *w); void makect(int nc, int *ip, DRCFloat *c); void cftfsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void cftbsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void rftfsub(int n, DRCFloat *a, int nc, DRCFloat *c); void rftbsub(int n, DRCFloat *a, int nc, DRCFloat *c); int nw, nc; DRCFloat xi; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 2)) { nc = n >> 2; makect(nc, ip, w + nw); } if (isgn >= 0) { if (n > 4) { cftfsub(n, a, ip, nw, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, ip, nw, w); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; } else { a[1] = ((DRCFloat) 0.5) * (a[0] - a[1]); a[0] -= a[1]; if (n > 4) { rftbsub(n, a, nc, w + nw); cftbsub(n, a, ip, nw, w); } else if (n == 4) { cftbsub(n, a, ip, nw, w); } } } void ddct(int n, int isgn, DRCFloat *a, int *ip, DRCFloat *w) { void makewt(int nw, int *ip, DRCFloat *w); void makect(int nc, int *ip, DRCFloat *c); void cftfsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void cftbsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void rftfsub(int n, DRCFloat *a, int nc, DRCFloat *c); void rftbsub(int n, DRCFloat *a, int nc, DRCFloat *c); void dctsub(int n, DRCFloat *a, int nc, DRCFloat *c); int j, nw, nc; DRCFloat xr; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > nc) { nc = n; makect(nc, ip, w + nw); } if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = a[j] - a[j - 1]; a[j] += a[j - 1]; } a[1] = a[0] - xr; a[0] += xr; if (n > 4) { rftbsub(n, a, nc, w + nw); cftbsub(n, a, ip, nw, w); } else if (n == 4) { cftbsub(n, a, ip, nw, w); } } dctsub(n, a, nc, w + nw); if (isgn >= 0) { if (n > 4) { cftfsub(n, a, ip, nw, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, ip, nw, w); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = a[j] - a[j + 1]; a[j] += a[j + 1]; } a[n - 1] = xr; } } void ddst(int n, int isgn, DRCFloat *a, int *ip, DRCFloat *w) { void makewt(int nw, int *ip, DRCFloat *w); void makect(int nc, int *ip, DRCFloat *c); void cftfsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void cftbsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void rftfsub(int n, DRCFloat *a, int nc, DRCFloat *c); void rftbsub(int n, DRCFloat *a, int nc, DRCFloat *c); void dstsub(int n, DRCFloat *a, int nc, DRCFloat *c); int j, nw, nc; DRCFloat xr; nw = ip[0]; if (n > (nw << 2)) { nw = n >> 2; makewt(nw, ip, w); } nc = ip[1]; if (n > nc) { nc = n; makect(nc, ip, w + nw); } if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = -a[j] - a[j - 1]; a[j] -= a[j - 1]; } a[1] = a[0] + xr; a[0] -= xr; if (n > 4) { rftbsub(n, a, nc, w + nw); cftbsub(n, a, ip, nw, w); } else if (n == 4) { cftbsub(n, a, ip, nw, w); } } dstsub(n, a, nc, w + nw); if (isgn >= 0) { if (n > 4) { cftfsub(n, a, ip, nw, w); rftfsub(n, a, nc, w + nw); } else if (n == 4) { cftfsub(n, a, ip, nw, w); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = -a[j] - a[j + 1]; a[j] -= a[j + 1]; } a[n - 1] = -xr; } } void dfct(int n, DRCFloat *a, DRCFloat *t, int *ip, DRCFloat *w) { void makewt(int nw, int *ip, DRCFloat *w); void makect(int nc, int *ip, DRCFloat *c); void cftfsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void rftfsub(int n, DRCFloat *a, int nc, DRCFloat *c); void dctsub(int n, DRCFloat *a, int nc, DRCFloat *c); int j, k, l, m, mh, nw, nc; DRCFloat xr, xi, yr, yi; nw = ip[0]; if (n > (nw << 3)) { nw = n >> 3; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 1)) { nc = n >> 1; makect(nc, ip, w + nw); } m = n >> 1; yi = a[m]; xi = a[0] + a[n]; a[0] -= a[n]; t[0] = xi - yi; t[m] = xi + yi; if (n > 2) { mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; xr = a[j] - a[n - j]; xi = a[j] + a[n - j]; yr = a[k] - a[n - k]; yi = a[k] + a[n - k]; a[j] = xr; a[k] = yr; t[j] = xi - yi; t[k] = xi + yi; } t[mh] = a[mh] + a[n - mh]; a[mh] -= a[n - mh]; dctsub(m, a, nc, w + nw); if (m > 4) { cftfsub(m, a, ip, nw, w); rftfsub(m, a, nc, w + nw); } else if (m == 4) { cftfsub(m, a, ip, nw, w); } a[n - 1] = a[0] - a[1]; a[1] = a[0] + a[1]; for (j = m - 2; j >= 2; j -= 2) { a[2 * j + 1] = a[j] + a[j + 1]; a[2 * j - 1] = a[j] - a[j + 1]; } l = 2; m = mh; while (m >= 2) { dctsub(m, t, nc, w + nw); if (m > 4) { cftfsub(m, t, ip, nw, w); rftfsub(m, t, nc, w + nw); } else if (m == 4) { cftfsub(m, t, ip, nw, w); } a[n - l] = t[0] - t[1]; a[l] = t[0] + t[1]; k = 0; for (j = 2; j < m; j += 2) { k += l << 2; a[k - l] = t[j] - t[j + 1]; a[k + l] = t[j] + t[j + 1]; } l <<= 1; mh = m >> 1; for (j = 0; j < mh; j++) { k = m - j; t[j] = t[m + k] - t[m + j]; t[k] = t[m + k] + t[m + j]; } t[mh] = t[m + mh]; m = mh; } a[l] = t[0]; a[n] = t[2] - t[1]; a[0] = t[2] + t[1]; } else { a[1] = a[0]; a[2] = t[0]; a[0] = t[1]; } } void dfst(int n, DRCFloat *a, DRCFloat *t, int *ip, DRCFloat *w) { void makewt(int nw, int *ip, DRCFloat *w); void makect(int nc, int *ip, DRCFloat *c); void cftfsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w); void rftfsub(int n, DRCFloat *a, int nc, DRCFloat *c); void dstsub(int n, DRCFloat *a, int nc, DRCFloat *c); int j, k, l, m, mh, nw, nc; DRCFloat xr, xi, yr, yi; nw = ip[0]; if (n > (nw << 3)) { nw = n >> 3; makewt(nw, ip, w); } nc = ip[1]; if (n > (nc << 1)) { nc = n >> 1; makect(nc, ip, w + nw); } if (n > 2) { m = n >> 1; mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; xr = a[j] + a[n - j]; xi = a[j] - a[n - j]; yr = a[k] + a[n - k]; yi = a[k] - a[n - k]; a[j] = xr; a[k] = yr; t[j] = xi + yi; t[k] = xi - yi; } t[0] = a[mh] - a[n - mh]; a[mh] += a[n - mh]; a[0] = a[m]; dstsub(m, a, nc, w + nw); if (m > 4) { cftfsub(m, a, ip, nw, w); rftfsub(m, a, nc, w + nw); } else if (m == 4) { cftfsub(m, a, ip, nw, w); } a[n - 1] = a[1] - a[0]; a[1] = a[0] + a[1]; for (j = m - 2; j >= 2; j -= 2) { a[2 * j + 1] = a[j] - a[j + 1]; a[2 * j - 1] = -a[j] - a[j + 1]; } l = 2; m = mh; while (m >= 2) { dstsub(m, t, nc, w + nw); if (m > 4) { cftfsub(m, t, ip, nw, w); rftfsub(m, t, nc, w + nw); } else if (m == 4) { cftfsub(m, t, ip, nw, w); } a[n - l] = t[1] - t[0]; a[l] = t[0] + t[1]; k = 0; for (j = 2; j < m; j += 2) { k += l << 2; a[k - l] = -t[j] - t[j + 1]; a[k + l] = t[j] - t[j + 1]; } l <<= 1; mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; t[j] = t[m + k] + t[m + j]; t[k] = t[m + k] - t[m + j]; } t[0] = t[m + mh]; m = mh; } a[l] = t[0]; } a[0] = 0; } /* -------- initializing routines -------- */ #include void makewt(int nw, int *ip, DRCFloat *w) { void makeipt(int nw, int *ip); int j, nwh, nw0, nw1; DRCFloat delta, wn4r, wk1r, wk1i, wk3r, wk3i; ip[0] = nw; ip[1] = 1; if (nw > 2) { nwh = nw >> 1; delta = ((DRCFloat) DRCATan(1.0)) / nwh; wn4r = (DRCFloat) DRCCos(delta * nwh); w[0] = 1; w[1] = wn4r; if (nwh == 4) { w[2] = (DRCFloat) DRCCos(delta * 2); w[3] = (DRCFloat) DRCSin(delta * 2); } else if (nwh > 4) { makeipt(nw, ip); w[2] = ((DRCFloat) 0.5) / (DRCFloat) DRCCos(delta * 2); w[3] = ((DRCFloat) 0.5) / (DRCFloat) DRCCos(delta * 6); for (j = 4; j < nwh; j += 4) { w[j] = (DRCFloat) DRCCos(delta * j); w[j + 1] = (DRCFloat) DRCSin(delta * j); w[j + 2] = (DRCFloat) DRCCos(3 * delta * j); w[j + 3] = (DRCFloat) -DRCSin(3 * delta * j); } } nw0 = 0; while (nwh > 2) { nw1 = nw0 + nwh; nwh >>= 1; w[nw1] = 1; w[nw1 + 1] = wn4r; if (nwh == 4) { wk1r = w[nw0 + 4]; wk1i = w[nw0 + 5]; w[nw1 + 2] = wk1r; w[nw1 + 3] = wk1i; } else if (nwh > 4) { wk1r = w[nw0 + 4]; wk3r = w[nw0 + 6]; w[nw1 + 2] = ((DRCFloat) 0.5) / wk1r; w[nw1 + 3] = ((DRCFloat) 0.5) / wk3r; for (j = 4; j < nwh; j += 4) { wk1r = w[nw0 + 2 * j]; wk1i = w[nw0 + 2 * j + 1]; wk3r = w[nw0 + 2 * j + 2]; wk3i = w[nw0 + 2 * j + 3]; w[nw1 + j] = wk1r; w[nw1 + j + 1] = wk1i; w[nw1 + j + 2] = wk3r; w[nw1 + j + 3] = wk3i; } } nw0 = nw1; } } } void makeipt(int nw, int *ip) { int j, l, m, m2, p, q; ip[2] = 0; ip[3] = 16; m = 2; for (l = nw; l > 32; l >>= 2) { m2 = m << 1; q = m2 << 3; for (j = m; j < m2; j++) { p = ip[j] << 2; ip[m + j] = p; ip[m2 + j] = p + q; } m = m2; } } void makect(int nc, int *ip, DRCFloat *c) { int j, nch; DRCFloat delta; ip[1] = nc; if (nc > 1) { nch = nc >> 1; delta = ((DRCFloat) DRCATan(1.0)) / (DRCFloat) nch; c[0] = (DRCFloat) DRCCos(delta * nch); c[nch] = ((DRCFloat) 0.5) * c[0]; for (j = 1; j < nch; j++) { c[j] = ((DRCFloat) 0.5) * (DRCFloat) DRCCos(delta * j); c[nc - j] = ((DRCFloat) 0.5) * (DRCFloat) DRCSin(delta * j); } } } /* -------- child routines -------- */ #ifdef USE_CDFT_PTHREADS #define USE_CDFT_THREADS #ifndef CDFT_THREADS_BEGIN_N #define CDFT_THREADS_BEGIN_N 8192 #endif #ifndef CDFT_4THREADS_BEGIN_N #define CDFT_4THREADS_BEGIN_N 65536 #endif #include #include #include #define cdft_thread_t pthread_t #define cdft_thread_create(thp,func,argp) { \ if (pthread_create(thp, NULL, func, (void *) argp) != 0) { \ fprintf(stderr, "cdft thread error\n"); \ exit(1); \ } \ } #define cdft_thread_wait(th) { \ if (pthread_join(th, NULL) != 0) { \ fprintf(stderr, "cdft thread error\n"); \ exit(1); \ } \ } #endif /* USE_CDFT_PTHREADS */ #ifdef USE_CDFT_WINTHREADS #define USE_CDFT_THREADS #ifndef CDFT_THREADS_BEGIN_N #define CDFT_THREADS_BEGIN_N 32768 #endif #ifndef CDFT_4THREADS_BEGIN_N #define CDFT_4THREADS_BEGIN_N 524288 #endif #include #include #include #define cdft_thread_t HANDLE #define cdft_thread_create(thp,func,argp) { \ DWORD thid; \ *(thp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, (LPVOID) argp, 0, &thid); \ if (*(thp) == 0) { \ fprintf(stderr, "cdft thread error\n"); \ exit(1); \ } \ } #define cdft_thread_wait(th) { \ WaitForSingleObject(th, INFINITE); \ CloseHandle(th); \ } #endif /* USE_CDFT_WINTHREADS */ void cftfsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w) { void bitrv2(int n, int *ip, DRCFloat *a); void bitrv216(DRCFloat *a); void bitrv208(DRCFloat *a); void cftf1st(int n, DRCFloat *a, DRCFloat *w); void cftrec4(int n, DRCFloat *a, int nw, DRCFloat *w); void cftleaf(int n, int isplt, DRCFloat *a, int nw, DRCFloat *w); void cftfx41(int n, DRCFloat *a, int nw, DRCFloat *w); void cftf161(DRCFloat *a, DRCFloat *w); void cftf081(DRCFloat *a, DRCFloat *w); void cftf040(DRCFloat *a); void cftx020(DRCFloat *a); #ifdef USE_CDFT_THREADS void cftrec4_th(int n, DRCFloat *a, int nw, DRCFloat *w); #endif /* USE_CDFT_THREADS */ if (n > 8) { if (n > 32) { cftf1st(n, a, &w[nw - (n >> 2)]); #ifdef USE_CDFT_THREADS if (n > CDFT_THREADS_BEGIN_N) { cftrec4_th(n, a, nw, w); } else #endif /* USE_CDFT_THREADS */ if (n > 512) { cftrec4(n, a, nw, w); } else if (n > 128) { cftleaf(n, 1, a, nw, w); } else { cftfx41(n, a, nw, w); } bitrv2(n, ip, a); } else if (n == 32) { cftf161(a, &w[nw - 8]); bitrv216(a); } else { cftf081(a, w); bitrv208(a); } } else if (n == 8) { cftf040(a); } else if (n == 4) { cftx020(a); } } void cftbsub(int n, DRCFloat *a, int *ip, int nw, DRCFloat *w) { void bitrv2conj(int n, int *ip, DRCFloat *a); void bitrv216neg(DRCFloat *a); void bitrv208neg(DRCFloat *a); void cftb1st(int n, DRCFloat *a, DRCFloat *w); void cftrec4(int n, DRCFloat *a, int nw, DRCFloat *w); void cftleaf(int n, int isplt, DRCFloat *a, int nw, DRCFloat *w); void cftfx41(int n, DRCFloat *a, int nw, DRCFloat *w); void cftf161(DRCFloat *a, DRCFloat *w); void cftf081(DRCFloat *a, DRCFloat *w); void cftb040(DRCFloat *a); void cftx020(DRCFloat *a); #ifdef USE_CDFT_THREADS void cftrec4_th(int n, DRCFloat *a, int nw, DRCFloat *w); #endif /* USE_CDFT_THREADS */ if (n > 8) { if (n > 32) { cftb1st(n, a, &w[nw - (n >> 2)]); #ifdef USE_CDFT_THREADS if (n > CDFT_THREADS_BEGIN_N) { cftrec4_th(n, a, nw, w); } else #endif /* USE_CDFT_THREADS */ if (n > 512) { cftrec4(n, a, nw, w); } else if (n > 128) { cftleaf(n, 1, a, nw, w); } else { cftfx41(n, a, nw, w); } bitrv2conj(n, ip, a); } else if (n == 32) { cftf161(a, &w[nw - 8]); bitrv216neg(a); } else { cftf081(a, w); bitrv208neg(a); } } else if (n == 8) { cftb040(a); } else if (n == 4) { cftx020(a); } } void bitrv2(int n, int *ip, DRCFloat *a) { int j, j1, k, k1, l, m, nh, nm; DRCFloat xr, xi, yr, yi; m = 1; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; nm = 4 * m; if (l == 8) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + 2 * ip[m + k]; k1 = 4 * k + 2 * ip[m + j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + 2 * ip[m + k]; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - nm; k1 += 2 * nm - 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } else { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + ip[m + k]; k1 = 4 * k + ip[m + j]; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + ip[m + k]; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } } } void bitrv2conj(int n, int *ip, DRCFloat *a) { int j, j1, k, k1, l, m, nh, nm; DRCFloat xr, xi, yr, yi; m = 1; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; nm = 4 * m; if (l == 8) { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + 2 * ip[m + k]; k1 = 4 * k + 2 * ip[m + j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + 2 * ip[m + k]; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += nm; k1 += 2 * nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - nm; k1 += 2 * nm - 2; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; } } else { for (k = 0; k < m; k++) { for (j = 0; j < k; j++) { j1 = 4 * j + ip[m + k]; k1 = 4 * k + ip[m + j]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nm; k1 += nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nm; k1 -= nm; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; } k1 = 4 * k + ip[m + k]; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += nm; k1 += nm; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; } } } void bitrv216(DRCFloat *a) { DRCFloat x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; a[2] = x8r; a[3] = x8i; a[4] = x4r; a[5] = x4i; a[6] = x12r; a[7] = x12i; a[8] = x2r; a[9] = x2i; a[10] = x10r; a[11] = x10i; a[14] = x14r; a[15] = x14i; a[16] = x1r; a[17] = x1i; a[20] = x5r; a[21] = x5i; a[22] = x13r; a[23] = x13i; a[24] = x3r; a[25] = x3i; a[26] = x11r; a[27] = x11i; a[28] = x7r; a[29] = x7i; } void bitrv216neg(DRCFloat *a) { DRCFloat x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x9r = a[18]; x9i = a[19]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; x15r = a[30]; x15i = a[31]; a[2] = x15r; a[3] = x15i; a[4] = x7r; a[5] = x7i; a[6] = x11r; a[7] = x11i; a[8] = x3r; a[9] = x3i; a[10] = x13r; a[11] = x13i; a[12] = x5r; a[13] = x5i; a[14] = x9r; a[15] = x9i; a[16] = x1r; a[17] = x1i; a[18] = x14r; a[19] = x14i; a[20] = x6r; a[21] = x6i; a[22] = x10r; a[23] = x10i; a[24] = x2r; a[25] = x2i; a[26] = x12r; a[27] = x12i; a[28] = x4r; a[29] = x4i; a[30] = x8r; a[31] = x8i; } void bitrv208(DRCFloat *a) { DRCFloat x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; x1r = a[2]; x1i = a[3]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x6r = a[12]; x6i = a[13]; a[2] = x4r; a[3] = x4i; a[6] = x6r; a[7] = x6i; a[8] = x1r; a[9] = x1i; a[12] = x3r; a[13] = x3i; } void bitrv208neg(DRCFloat *a) { DRCFloat x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; a[2] = x7r; a[3] = x7i; a[4] = x3r; a[5] = x3i; a[6] = x5r; a[7] = x5i; a[8] = x1r; a[9] = x1i; a[10] = x6r; a[11] = x6i; a[12] = x2r; a[13] = x2i; a[14] = x4r; a[15] = x4i; } void cftf1st(int n, DRCFloat *a, DRCFloat *w) { int j, j0, j1, j2, j3, k, m, mh; DRCFloat wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; DRCFloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = a[1] + a[j2 + 1]; x1r = a[0] - a[j2]; x1i = a[1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j2] = x1r - x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; csc1 = w[2]; csc3 = w[3]; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; k = 0; for (j = 2; j < mh - 2; j += 4) { k += 4; wk1r = csc1 * (wd1r + w[k]); wk1i = csc1 * (wd1i + w[k + 1]); wk3r = csc3 * (wd3r + w[k + 2]); wk3i = csc3 * (wd3i + w[k + 3]); wd1r = w[k]; wd1i = w[k + 1]; wd3r = w[k + 2]; wd3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = a[j + 1] + a[j2 + 1]; x1r = a[j] - a[j2]; x1i = a[j + 1] - a[j2 + 1]; y0r = a[j + 2] + a[j2 + 2]; y0i = a[j + 3] + a[j2 + 3]; y1r = a[j + 2] - a[j2 + 2]; y1i = a[j + 3] - a[j2 + 3]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 + 2] + a[j3 + 2]; y2i = a[j1 + 3] + a[j3 + 3]; y3r = a[j1 + 2] - a[j3 + 2]; y3i = a[j1 + 3] - a[j3 + 3]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j + 2] = y0r + y2r; a[j + 3] = y0i + y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i - y2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = y1r - y3i; x0i = y1i + y3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = y1r + y3i; x0i = y1i - y3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; y0r = a[j0 - 2] + a[j2 - 2]; y0i = a[j0 - 1] + a[j2 - 1]; y1r = a[j0 - 2] - a[j2 - 2]; y1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 - 2] + a[j3 - 2]; y2i = a[j1 - 1] + a[j3 - 1]; y3r = a[j1 - 2] - a[j3 - 2]; y3i = a[j1 - 1] - a[j3 - 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i + y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i - y2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = y1r - y3i; x0i = y1i + y3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = y1r + y3i; x0i = y1i - y3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; } wk1r = csc1 * (wd1r + wn4r); wk1i = csc1 * (wd1i + wn4r); wk3r = csc3 * (wd3r - wn4r); wk3i = csc3 * (wd3i - wn4r); j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = a[j0 - 1] + a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i + x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = a[j0 + 3] + a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = a[j0 + 3] - a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i + x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } void cftb1st(int n, DRCFloat *a, DRCFloat *w) { int j, j0, j1, j2, j3, k, m, mh; DRCFloat wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; DRCFloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = -a[1] - a[j2 + 1]; x1r = a[0] - a[j2]; x1i = -a[1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j2] = x1r + x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r - x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; csc1 = w[2]; csc3 = w[3]; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; k = 0; for (j = 2; j < mh - 2; j += 4) { k += 4; wk1r = csc1 * (wd1r + w[k]); wk1i = csc1 * (wd1i + w[k + 1]); wk3r = csc3 * (wd3r + w[k + 2]); wk3i = csc3 * (wd3i + w[k + 3]); wd1r = w[k]; wd1i = w[k + 1]; wd3r = w[k + 2]; wd3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = -a[j + 1] - a[j2 + 1]; x1r = a[j] - a[j2]; x1i = -a[j + 1] + a[j2 + 1]; y0r = a[j + 2] + a[j2 + 2]; y0i = -a[j + 3] - a[j2 + 3]; y1r = a[j + 2] - a[j2 + 2]; y1i = -a[j + 3] + a[j2 + 3]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 + 2] + a[j3 + 2]; y2i = a[j1 + 3] + a[j3 + 3]; y3r = a[j1 + 2] - a[j3 + 2]; y3i = a[j1 + 3] - a[j3 + 3]; a[j] = x0r + x2r; a[j + 1] = x0i - x2i; a[j + 2] = y0r + y2r; a[j + 3] = y0i - y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i + y2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = y1r + y3i; x0i = y1i + y3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = y1r - y3i; x0i = y1i - y3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; y0r = a[j0 - 2] + a[j2 - 2]; y0i = -a[j0 - 1] - a[j2 - 1]; y1r = a[j0 - 2] - a[j2 - 2]; y1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; y2r = a[j1 - 2] + a[j3 - 2]; y2i = a[j1 - 1] + a[j3 - 1]; y3r = a[j1 - 2] - a[j3 - 2]; y3i = a[j1 - 1] - a[j3 - 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i - y2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i + y2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = y1r + y3i; x0i = y1i + y3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = y1r - y3i; x0i = y1i - y3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; } wk1r = csc1 * (wd1r + wn4r); wk1i = csc1 * (wd1i + wn4r); wk3r = csc3 * (wd3r - wn4r); wk3i = csc3 * (wd3i - wn4r); j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = -a[j0 - 1] - a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i - x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = -a[j0 + 3] - a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = -a[j0 + 3] + a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i - x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } #ifdef USE_CDFT_THREADS struct cdft_arg_st { int n0; int n; DRCFloat *a; int nw; DRCFloat *w; }; typedef struct cdft_arg_st cdft_arg_t; void cftrec4_th(int n, DRCFloat *a, int nw, DRCFloat *w) { void *cftrec1_th(void *p); void *cftrec2_th(void *p); int i, idiv4, m, nthread; cdft_thread_t th[4]; cdft_arg_t ag[4]; nthread = 2; idiv4 = 0; m = n >> 1; if (n > CDFT_4THREADS_BEGIN_N) { nthread = 4; idiv4 = 1; m >>= 1; } for (i = 0; i < nthread; i++) { ag[i].n0 = n; ag[i].n = m; ag[i].a = &a[i * m]; ag[i].nw = nw; ag[i].w = w; if (i != idiv4) { cdft_thread_create(&th[i], cftrec1_th, &ag[i]); } else { cdft_thread_create(&th[i], cftrec2_th, &ag[i]); } } for (i = 0; i < nthread; i++) { cdft_thread_wait(th[i]); } } void *cftrec1_th(void *p) { int cfttree(int n, int j, int k, DRCFloat *a, int nw, DRCFloat *w); void cftleaf(int n, int isplt, DRCFloat *a, int nw, DRCFloat *w); void cftmdl1(int n, DRCFloat *a, DRCFloat *w); int isplt, j, k, m, n, n0, nw; DRCFloat *a, *w; n0 = ((cdft_arg_t *) p)->n0; n = ((cdft_arg_t *) p)->n; a = ((cdft_arg_t *) p)->a; nw = ((cdft_arg_t *) p)->nw; w = ((cdft_arg_t *) p)->w; m = n0; while (m > 512) { m >>= 2; cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); } cftleaf(m, 1, &a[n - m], nw, w); k = 0; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a, nw, w); cftleaf(m, isplt, &a[j - m], nw, w); } return (void *) 0; } void *cftrec2_th(void *p) { int cfttree(int n, int j, int k, DRCFloat *a, int nw, DRCFloat *w); void cftleaf(int n, int isplt, DRCFloat *a, int nw, DRCFloat *w); void cftmdl2(int n, DRCFloat *a, DRCFloat *w); int isplt, j, k, m, n, n0, nw; DRCFloat *a, *w; n0 = ((cdft_arg_t *) p)->n0; n = ((cdft_arg_t *) p)->n; a = ((cdft_arg_t *) p)->a; nw = ((cdft_arg_t *) p)->nw; w = ((cdft_arg_t *) p)->w; k = 1; m = n0; while (m > 512) { m >>= 2; k <<= 2; cftmdl2(m, &a[n - m], &w[nw - m]); } cftleaf(m, 0, &a[n - m], nw, w); k >>= 1; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a, nw, w); cftleaf(m, isplt, &a[j - m], nw, w); } return (void *) 0; } #endif /* USE_CDFT_THREADS */ void cftrec4(int n, DRCFloat *a, int nw, DRCFloat *w) { int cfttree(int n, int j, int k, DRCFloat *a, int nw, DRCFloat *w); void cftleaf(int n, int isplt, DRCFloat *a, int nw, DRCFloat *w); void cftmdl1(int n, DRCFloat *a, DRCFloat *w); int isplt, j, k, m; m = n; while (m > 512) { m >>= 2; cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]); } cftleaf(m, 1, &a[n - m], nw, w); k = 0; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a, nw, w); cftleaf(m, isplt, &a[j - m], nw, w); } } int cfttree(int n, int j, int k, DRCFloat *a, int nw, DRCFloat *w) { void cftmdl1(int n, DRCFloat *a, DRCFloat *w); void cftmdl2(int n, DRCFloat *a, DRCFloat *w); int i, isplt, m; if ((k & 3) != 0) { isplt = k & 1; if (isplt != 0) { cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]); } else { cftmdl2(n, &a[j - n], &w[nw - n]); } } else { m = n; for (i = k; (i & 3) == 0; i >>= 2) { m <<= 2; } isplt = i & 1; if (isplt != 0) { while (m > 128) { cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]); m >>= 2; } } else { while (m > 128) { cftmdl2(m, &a[j - m], &w[nw - m]); m >>= 2; } } } return isplt; } void cftleaf(int n, int isplt, DRCFloat *a, int nw, DRCFloat *w) { void cftmdl1(int n, DRCFloat *a, DRCFloat *w); void cftmdl2(int n, DRCFloat *a, DRCFloat *w); void cftf161(DRCFloat *a, DRCFloat *w); void cftf162(DRCFloat *a, DRCFloat *w); void cftf081(DRCFloat *a, DRCFloat *w); void cftf082(DRCFloat *a, DRCFloat *w); if (n == 512) { cftmdl1(128, a, &w[nw - 64]); cftf161(a, &w[nw - 8]); cftf162(&a[32], &w[nw - 32]); cftf161(&a[64], &w[nw - 8]); cftf161(&a[96], &w[nw - 8]); cftmdl2(128, &a[128], &w[nw - 128]); cftf161(&a[128], &w[nw - 8]); cftf162(&a[160], &w[nw - 32]); cftf161(&a[192], &w[nw - 8]); cftf162(&a[224], &w[nw - 32]); cftmdl1(128, &a[256], &w[nw - 64]); cftf161(&a[256], &w[nw - 8]); cftf162(&a[288], &w[nw - 32]); cftf161(&a[320], &w[nw - 8]); cftf161(&a[352], &w[nw - 8]); if (isplt != 0) { cftmdl1(128, &a[384], &w[nw - 64]); cftf161(&a[480], &w[nw - 8]); } else { cftmdl2(128, &a[384], &w[nw - 128]); cftf162(&a[480], &w[nw - 32]); } cftf161(&a[384], &w[nw - 8]); cftf162(&a[416], &w[nw - 32]); cftf161(&a[448], &w[nw - 8]); } else { cftmdl1(64, a, &w[nw - 32]); cftf081(a, &w[nw - 8]); cftf082(&a[16], &w[nw - 8]); cftf081(&a[32], &w[nw - 8]); cftf081(&a[48], &w[nw - 8]); cftmdl2(64, &a[64], &w[nw - 64]); cftf081(&a[64], &w[nw - 8]); cftf082(&a[80], &w[nw - 8]); cftf081(&a[96], &w[nw - 8]); cftf082(&a[112], &w[nw - 8]); cftmdl1(64, &a[128], &w[nw - 32]); cftf081(&a[128], &w[nw - 8]); cftf082(&a[144], &w[nw - 8]); cftf081(&a[160], &w[nw - 8]); cftf081(&a[176], &w[nw - 8]); if (isplt != 0) { cftmdl1(64, &a[192], &w[nw - 32]); cftf081(&a[240], &w[nw - 8]); } else { cftmdl2(64, &a[192], &w[nw - 64]); cftf082(&a[240], &w[nw - 8]); } cftf081(&a[192], &w[nw - 8]); cftf082(&a[208], &w[nw - 8]); cftf081(&a[224], &w[nw - 8]); } } void cftmdl1(int n, DRCFloat *a, DRCFloat *w) { int j, j0, j1, j2, j3, k, m, mh; DRCFloat wn4r, wk1r, wk1i, wk3r, wk3i; DRCFloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = a[1] + a[j2 + 1]; x1r = a[0] - a[j2]; x1i = a[1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j2] = x1r - x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; wn4r = w[1]; k = 0; for (j = 2; j < mh; j += 2) { k += 4; wk1r = w[k]; wk1i = w[k + 1]; wk3r = w[k + 2]; wk3i = w[k + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = a[j + 1] + a[j2 + 1]; x1r = a[j] - a[j2]; x1i = a[j + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; } j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wn4r * (x0r - x0i); a[j2 + 1] = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = -wn4r * (x0r + x0i); a[j3 + 1] = -wn4r * (x0i - x0r); } void cftmdl2(int n, DRCFloat *a, DRCFloat *w) { int j, j0, j1, j2, j3, k, kr, m, mh; DRCFloat wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i; DRCFloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; mh = n >> 3; m = 2 * mh; wn4r = w[1]; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] - a[j2 + 1]; x0i = a[1] + a[j2]; x1r = a[0] + a[j2 + 1]; x1i = a[1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wn4r * (x2r - x2i); y0i = wn4r * (x2i + x2r); a[0] = x0r + y0r; a[1] = x0i + y0i; a[j1] = x0r - y0r; a[j1 + 1] = x0i - y0i; y0r = wn4r * (x3r - x3i); y0i = wn4r * (x3i + x3r); a[j2] = x1r - y0i; a[j2 + 1] = x1i + y0r; a[j3] = x1r + y0i; a[j3 + 1] = x1i - y0r; k = 0; kr = 2 * m; for (j = 2; j < mh; j += 2) { k += 4; wk1r = w[k]; wk1i = w[k + 1]; wk3r = w[k + 2]; wk3i = w[k + 3]; kr -= 4; wd1i = w[kr]; wd1r = w[kr + 1]; wd3i = w[kr + 2]; wd3r = w[kr + 3]; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] - a[j2 + 1]; x0i = a[j + 1] + a[j2]; x1r = a[j] + a[j2 + 1]; x1i = a[j + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wd1r * x2r - wd1i * x2i; y2i = wd1r * x2i + wd1i * x2r; a[j] = y0r + y2r; a[j + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wk3r * x1r + wk3i * x1i; y0i = wk3r * x1i - wk3i * x1r; y2r = wd3r * x3r + wd3i * x3i; y2i = wd3r * x3i - wd3i * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wd1i * x0r - wd1r * x0i; y0i = wd1i * x0i + wd1r * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wd3i * x1r + wd3r * x1i; y0i = wd3i * x1i - wd3r * x1r; y2r = wk3i * x3r + wk3r * x3i; y2i = wk3i * x3i - wk3r * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; } wk1r = w[m]; wk1i = w[m + 1]; j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wk1i * x1r - wk1r * x1i; y0i = wk1i * x1i + wk1r * x1r; y2r = wk1r * x3r - wk1i * x3i; y2i = wk1r * x3i + wk1i * x3r; a[j2] = y0r - y2r; a[j2 + 1] = y0i - y2i; a[j3] = y0r + y2r; a[j3 + 1] = y0i + y2i; } void cftfx41(int n, DRCFloat *a, int nw, DRCFloat *w) { void cftf161(DRCFloat *a, DRCFloat *w); void cftf162(DRCFloat *a, DRCFloat *w); void cftf081(DRCFloat *a, DRCFloat *w); void cftf082(DRCFloat *a, DRCFloat *w); if (n == 128) { cftf161(a, &w[nw - 8]); cftf162(&a[32], &w[nw - 32]); cftf161(&a[64], &w[nw - 8]); cftf161(&a[96], &w[nw - 8]); } else { cftf081(a, &w[nw - 8]); cftf082(&a[16], &w[nw - 8]); cftf081(&a[32], &w[nw - 8]); cftf081(&a[48], &w[nw - 8]); } } void cftf161(DRCFloat *a, DRCFloat *w) { DRCFloat wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = w[1]; wk1r = w[2]; wk1i = w[3]; x0r = a[0] + a[16]; x0i = a[1] + a[17]; x1r = a[0] - a[16]; x1i = a[1] - a[17]; x2r = a[8] + a[24]; x2i = a[9] + a[25]; x3r = a[8] - a[24]; x3i = a[9] - a[25]; y0r = x0r + x2r; y0i = x0i + x2i; y4r = x0r - x2r; y4i = x0i - x2i; y8r = x1r - x3i; y8i = x1i + x3r; y12r = x1r + x3i; y12i = x1i - x3r; x0r = a[2] + a[18]; x0i = a[3] + a[19]; x1r = a[2] - a[18]; x1i = a[3] - a[19]; x2r = a[10] + a[26]; x2i = a[11] + a[27]; x3r = a[10] - a[26]; x3i = a[11] - a[27]; y1r = x0r + x2r; y1i = x0i + x2i; y5r = x0r - x2r; y5i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y9r = wk1r * x0r - wk1i * x0i; y9i = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y13r = wk1i * x0r - wk1r * x0i; y13i = wk1i * x0i + wk1r * x0r; x0r = a[4] + a[20]; x0i = a[5] + a[21]; x1r = a[4] - a[20]; x1i = a[5] - a[21]; x2r = a[12] + a[28]; x2i = a[13] + a[29]; x3r = a[12] - a[28]; x3i = a[13] - a[29]; y2r = x0r + x2r; y2i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y10r = wn4r * (x0r - x0i); y10i = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; y14r = wn4r * (x0r + x0i); y14i = wn4r * (x0i - x0r); x0r = a[6] + a[22]; x0i = a[7] + a[23]; x1r = a[6] - a[22]; x1i = a[7] - a[23]; x2r = a[14] + a[30]; x2i = a[15] + a[31]; x3r = a[14] - a[30]; x3i = a[15] - a[31]; y3r = x0r + x2r; y3i = x0i + x2i; y7r = x0r - x2r; y7i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y11r = wk1i * x0r - wk1r * x0i; y11i = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y15r = wk1r * x0r - wk1i * x0i; y15i = wk1r * x0i + wk1i * x0r; x0r = y12r - y14r; x0i = y12i - y14i; x1r = y12r + y14r; x1i = y12i + y14i; x2r = y13r - y15r; x2i = y13i - y15i; x3r = y13r + y15r; x3i = y13i + y15i; a[24] = x0r + x2r; a[25] = x0i + x2i; a[26] = x0r - x2r; a[27] = x0i - x2i; a[28] = x1r - x3i; a[29] = x1i + x3r; a[30] = x1r + x3i; a[31] = x1i - x3r; x0r = y8r + y10r; x0i = y8i + y10i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; x3r = y9r - y11r; x3i = y9i - y11i; a[16] = x0r + x2r; a[17] = x0i + x2i; a[18] = x0r - x2r; a[19] = x0i - x2i; a[20] = x1r - x3i; a[21] = x1i + x3r; a[22] = x1r + x3i; a[23] = x1i - x3r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); x0r = y5r + y7i; x0i = y5i - y7r; x3r = wn4r * (x0r - x0i); x3i = wn4r * (x0i + x0r); x0r = y4r - y6i; x0i = y4i + y6r; x1r = y4r + y6i; x1i = y4i - y6r; a[8] = x0r + x2r; a[9] = x0i + x2i; a[10] = x0r - x2r; a[11] = x0i - x2i; a[12] = x1r - x3i; a[13] = x1i + x3r; a[14] = x1r + x3i; a[15] = x1i - x3r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r + y3r; x2i = y1i + y3i; x3r = y1r - y3r; x3i = y1i - y3i; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x0r - x2r; a[3] = x0i - x2i; a[4] = x1r - x3i; a[5] = x1i + x3r; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftf162(DRCFloat *a, DRCFloat *w) { DRCFloat wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = w[1]; wk1r = w[4]; wk1i = w[5]; wk3r = w[6]; wk3i = -w[7]; wk2r = w[8]; wk2i = w[9]; x1r = a[0] - a[17]; x1i = a[1] + a[16]; x0r = a[8] - a[25]; x0i = a[9] + a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y0r = x1r + x2r; y0i = x1i + x2i; y4r = x1r - x2r; y4i = x1i - x2i; x1r = a[0] + a[17]; x1i = a[1] - a[16]; x0r = a[8] + a[25]; x0i = a[9] - a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y8r = x1r - x2i; y8i = x1i + x2r; y12r = x1r + x2i; y12i = x1i - x2r; x0r = a[2] - a[19]; x0i = a[3] + a[18]; x1r = wk1r * x0r - wk1i * x0i; x1i = wk1r * x0i + wk1i * x0r; x0r = a[10] - a[27]; x0i = a[11] + a[26]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y1r = x1r + x2r; y1i = x1i + x2i; y5r = x1r - x2r; y5i = x1i - x2i; x0r = a[2] + a[19]; x0i = a[3] - a[18]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[10] + a[27]; x0i = a[11] - a[26]; x2r = wk1r * x0r + wk1i * x0i; x2i = wk1r * x0i - wk1i * x0r; y9r = x1r - x2r; y9i = x1i - x2i; y13r = x1r + x2r; y13i = x1i + x2i; x0r = a[4] - a[21]; x0i = a[5] + a[20]; x1r = wk2r * x0r - wk2i * x0i; x1i = wk2r * x0i + wk2i * x0r; x0r = a[12] - a[29]; x0i = a[13] + a[28]; x2r = wk2i * x0r - wk2r * x0i; x2i = wk2i * x0i + wk2r * x0r; y2r = x1r + x2r; y2i = x1i + x2i; y6r = x1r - x2r; y6i = x1i - x2i; x0r = a[4] + a[21]; x0i = a[5] - a[20]; x1r = wk2i * x0r - wk2r * x0i; x1i = wk2i * x0i + wk2r * x0r; x0r = a[12] + a[29]; x0i = a[13] - a[28]; x2r = wk2r * x0r - wk2i * x0i; x2i = wk2r * x0i + wk2i * x0r; y10r = x1r - x2r; y10i = x1i - x2i; y14r = x1r + x2r; y14i = x1i + x2i; x0r = a[6] - a[23]; x0i = a[7] + a[22]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[14] - a[31]; x0i = a[15] + a[30]; x2r = wk1i * x0r - wk1r * x0i; x2i = wk1i * x0i + wk1r * x0r; y3r = x1r + x2r; y3i = x1i + x2i; y7r = x1r - x2r; y7i = x1i - x2i; x0r = a[6] + a[23]; x0i = a[7] - a[22]; x1r = wk1i * x0r + wk1r * x0i; x1i = wk1i * x0i - wk1r * x0r; x0r = a[14] + a[31]; x0i = a[15] - a[30]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y11r = x1r + x2r; y11i = x1i + x2i; y15r = x1r - x2r; y15i = x1i - x2i; x1r = y0r + y2r; x1i = y0i + y2i; x2r = y1r + y3r; x2i = y1i + y3i; a[0] = x1r + x2r; a[1] = x1i + x2i; a[2] = x1r - x2r; a[3] = x1i - x2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r - y3r; x2i = y1i - y3i; a[4] = x1r - x2i; a[5] = x1i + x2r; a[6] = x1r + x2i; a[7] = x1i - x2r; x1r = y4r - y6i; x1i = y4i + y6r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[8] = x1r + x2r; a[9] = x1i + x2i; a[10] = x1r - x2r; a[11] = x1i - x2i; x1r = y4r + y6i; x1i = y4i - y6r; x0r = y5r + y7i; x0i = y5i - y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[12] = x1r - x2i; a[13] = x1i + x2r; a[14] = x1r + x2i; a[15] = x1i - x2r; x1r = y8r + y10r; x1i = y8i + y10i; x2r = y9r - y11r; x2i = y9i - y11i; a[16] = x1r + x2r; a[17] = x1i + x2i; a[18] = x1r - x2r; a[19] = x1i - x2i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; a[20] = x1r - x2i; a[21] = x1i + x2r; a[22] = x1r + x2i; a[23] = x1i - x2r; x1r = y12r - y14i; x1i = y12i + y14r; x0r = y13r + y15i; x0i = y13i - y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[24] = x1r + x2r; a[25] = x1i + x2i; a[26] = x1r - x2r; a[27] = x1i - x2i; x1r = y12r + y14i; x1i = y12i - y14r; x0r = y13r - y15i; x0i = y13i + y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[28] = x1r - x2i; a[29] = x1i + x2r; a[30] = x1r + x2i; a[31] = x1i - x2r; } void cftf081(DRCFloat *a, DRCFloat *w) { DRCFloat wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = w[1]; x0r = a[0] + a[8]; x0i = a[1] + a[9]; x1r = a[0] - a[8]; x1i = a[1] - a[9]; x2r = a[4] + a[12]; x2i = a[5] + a[13]; x3r = a[4] - a[12]; x3i = a[5] - a[13]; y0r = x0r + x2r; y0i = x0i + x2i; y2r = x0r - x2r; y2i = x0i - x2i; y1r = x1r - x3i; y1i = x1i + x3r; y3r = x1r + x3i; y3i = x1i - x3r; x0r = a[2] + a[10]; x0i = a[3] + a[11]; x1r = a[2] - a[10]; x1i = a[3] - a[11]; x2r = a[6] + a[14]; x2i = a[7] + a[15]; x3r = a[6] - a[14]; x3i = a[7] - a[15]; y4r = x0r + x2r; y4i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; x2r = x1r + x3i; x2i = x1i - x3r; y5r = wn4r * (x0r - x0i); y5i = wn4r * (x0r + x0i); y7r = wn4r * (x2r - x2i); y7i = wn4r * (x2r + x2i); a[8] = y1r + y5r; a[9] = y1i + y5i; a[10] = y1r - y5r; a[11] = y1i - y5i; a[12] = y3r - y7i; a[13] = y3i + y7r; a[14] = y3r + y7i; a[15] = y3i - y7r; a[0] = y0r + y4r; a[1] = y0i + y4i; a[2] = y0r - y4r; a[3] = y0i - y4i; a[4] = y2r - y6i; a[5] = y2i + y6r; a[6] = y2r + y6i; a[7] = y2i - y6r; } void cftf082(DRCFloat *a, DRCFloat *w) { DRCFloat wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = w[1]; wk1r = w[2]; wk1i = w[3]; y0r = a[0] - a[9]; y0i = a[1] + a[8]; y1r = a[0] + a[9]; y1i = a[1] - a[8]; x0r = a[4] - a[13]; x0i = a[5] + a[12]; y2r = wn4r * (x0r - x0i); y2i = wn4r * (x0i + x0r); x0r = a[4] + a[13]; x0i = a[5] - a[12]; y3r = wn4r * (x0r - x0i); y3i = wn4r * (x0i + x0r); x0r = a[2] - a[11]; x0i = a[3] + a[10]; y4r = wk1r * x0r - wk1i * x0i; y4i = wk1r * x0i + wk1i * x0r; x0r = a[2] + a[11]; x0i = a[3] - a[10]; y5r = wk1i * x0r - wk1r * x0i; y5i = wk1i * x0i + wk1r * x0r; x0r = a[6] - a[15]; x0i = a[7] + a[14]; y6r = wk1i * x0r - wk1r * x0i; y6i = wk1i * x0i + wk1r * x0r; x0r = a[6] + a[15]; x0i = a[7] - a[14]; y7r = wk1r * x0r - wk1i * x0i; y7i = wk1r * x0i + wk1i * x0r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y4r + y6r; x1i = y4i + y6i; a[0] = x0r + x1r; a[1] = x0i + x1i; a[2] = x0r - x1r; a[3] = x0i - x1i; x0r = y0r - y2r; x0i = y0i - y2i; x1r = y4r - y6r; x1i = y4i - y6i; a[4] = x0r - x1i; a[5] = x0i + x1r; a[6] = x0r + x1i; a[7] = x0i - x1r; x0r = y1r - y3i; x0i = y1i + y3r; x1r = y5r - y7r; x1i = y5i - y7i; a[8] = x0r + x1r; a[9] = x0i + x1i; a[10] = x0r - x1r; a[11] = x0i - x1i; x0r = y1r + y3i; x0i = y1i - y3r; x1r = y5r + y7r; x1i = y5i + y7i; a[12] = x0r - x1i; a[13] = x0i + x1r; a[14] = x0r + x1i; a[15] = x0i - x1r; } void cftf040(DRCFloat *a) { DRCFloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r - x3i; a[3] = x1i + x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftb040(DRCFloat *a) { DRCFloat x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r + x3i; a[3] = x1i - x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r - x3i; a[7] = x1i + x3r; } void cftx020(DRCFloat *a) { DRCFloat x0r, x0i; x0r = a[0] - a[2]; x0i = a[1] - a[3]; a[0] += a[2]; a[1] += a[3]; a[2] = x0r; a[3] = x0i; } void rftfsub(int n, DRCFloat *a, int nc, DRCFloat *c) { int j, k, kk, ks, m; DRCFloat wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = ((DRCFloat) 0.5) - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void rftbsub(int n, DRCFloat *a, int nc, DRCFloat *c) { int j, k, kk, ks, m; DRCFloat wkr, wki, xr, xi, yr, yi; m = n >> 1; ks = 2 * nc / m; kk = 0; for (j = 2; j < m; j += 2) { k = n - j; kk += ks; wkr = ((DRCFloat) 0.5) - c[nc - kk]; wki = c[kk]; xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr + wki * xi; yi = wkr * xi - wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; } } void dctsub(int n, DRCFloat *a, int nc, DRCFloat *c) { int j, k, kk, ks, m; DRCFloat wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[j] - wkr * a[k]; a[j] = wkr * a[j] + wki * a[k]; a[k] = xr; } a[m] *= c[0]; } void dstsub(int n, DRCFloat *a, int nc, DRCFloat *c) { int j, k, kk, ks, m; DRCFloat wkr, wki, xr; m = n >> 1; ks = nc / n; kk = 0; for (j = 1; j < m; j++) { k = n - j; kk += ks; wkr = c[kk] - c[nc - kk]; wki = c[kk] + c[nc - kk]; xr = wki * a[k] - wkr * a[j]; a[k] = wkr * a[k] + wki * a[j]; a[j] = xr; } a[m] *= c[0]; } drc-3.2.2/source/readme.txt0000644000076400001450000000211313163367107014553 0ustar denisitadmDRC: Digital Room Correction Copyright (C) 2002-2017 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 Foun dation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. You can contact the author on Internet at the following address: d.sbragion@neomerica.it All the documentation for DRC is under the doc subdirectory and is available in html format. The html is also available on-line at: - http://drc-fir.sourceforge.net/doc/drc.html The official DRC home page is at: - http://drc-fir.sourceforge.net/ drc-3.2.2/source/drc-3.2.2.lsm0000644000076400001450000000110013162151444014467 0ustar denisitadmBegin4 Title: DRC: Digital Room Correction Version: 3.2.2 Entered-date: 2017-10-01 Description: DRC generates digital room correction FIR filters to be used within HiFi systems in conjunction with real time convolution engines like BruteFIR. Keywords: digital room correction, real time equalization, fir filters Author: d.sbragion@neomerica.it (Denis Sbragion) Maintained-by: d.sbragion@neomerica.it (Denis Sbragion), Primary-site: drc-fir.sourceforge.net Alternate-site: Original-site: Platforms: Linux, POSIX, Win32 Copying-policy: GPL End drc-3.2.2/source/mic/0000755000076400001450000000000013165107360013323 5ustar denisitadmdrc-3.2.2/source/mic/wm-60a.txt0000644000076400001450000000703311320622201015061 0ustar denisitadm000.000000 0.336000 -0.700000 300.622000 0.336000 -0.700000 312.476000 0.321000 -0.500000 324.797000 0.304000 -1.000000 337.605000 0.286000 -0.600000 350.917000 0.268000 -1.400000 364.754000 0.248000 -0.800000 379.136000 0.229000 -1.400000 394.086000 0.204000 -1.400000 409.625000 0.183000 -0.900000 425.777000 0.172000 -1.500000 442.566000 0.153000 -1.600000 460.017000 0.138000 -1.200000 478.156000 0.123000 -1.100000 497.010000 0.111000 -1.400000 516.608000 0.099000 -1.600000 536.978000 0.090000 -1.600000 558.152000 0.080000 -1.400000 580.160000 0.072000 -1.400000 603.037000 0.060000 -1.400000 626.815000 0.052000 -1.400000 651.531000 0.044000 -1.400000 677.222000 0.035000 -1.500000 703.925000 0.027000 -1.600000 731.682000 0.021000 -1.400000 760.533000 0.018000 -1.100000 790.521000 0.020000 -1.300000 821.693000 0.024000 -1.500000 854.093000 0.028000 -1.200000 887.771000 0.030000 -1.500000 922.776000 0.027000 -1.400000 959.162000 0.019000 -1.800000 996.983000 -0.000000 -1.600000 1036.30000 -0.020000 -1.800000 1077.16000 -0.040000 -1.900000 1119.630000 -0.070000 -1.700000 1163.780000 -0.080000 -1.500000 1209.670000 -0.080000 -1.300000 1257.370000 -0.070000 -1.200000 1306.950000 -0.050000 -1.300000 1358.480000 -0.030000 -1.400000 1412.050000 -0.010000 -1.500000 1467.730000 -0.010000 -1.600000 1525.600000 -0.030000 -1.900000 1585.760000 -0.050000 -1.800000 1648.280000 -0.080000 -1.800000 1713.280000 -0.080000 -1.700000 1780.830000 -0.070000 -1.700000 1851.050000 -0.060000 -1.700000 1924.040000 -0.060000 -1.700000 1999.910000 -0.060000 -1.500000 2078.770000 -0.040000 -1.400000 2160.740000 0.006000 -1.400000 2245.940000 0.063000 -1.700000 2334.500000 0.090000 -2.100000 2426.550000 0.074000 -2.600000 2522.230000 0.028000 -2.900000 2621.680000 -0.030000 -3.100000 2725.060000 -0.050000 -3.000000 2832.510000 -0.050000 -3.000000 2944.200000 -0.050000 -3.100000 3060.290000 -0.090000 -3.300000 3180.960000 -0.140000 -3.200000 3306.390000 -0.140000 -3.000000 3436.770000 -0.080000 -2.900000 3572.280000 -0.040000 -3.300000 3713.140000 -0.080000 -3.800000 3859.560000 -0.150000 -3.800000 4011.740000 -0.160000 -3.500000 4169.930000 -0.120000 -3.400000 4334.350000 -0.080000 -3.600000 4505.260000 -0.060000 -3.900000 4682.910000 -0.080000 -4.200000 4867.560000 -0.070000 -4.100000 5059.490000 -0.000000 -4.600000 5259.000000 -0.020000 -5.500000 5466.360000 -0.140000 -6.100000 5681.910000 -0.250000 -5.700000 5905.950000 -0.220000 -5.500000 6138.830000 -0.200000 -5.500000 6380.890000 -0.170000 -5.900000 6632.500000 -0.190000 -6.400000 6894.020000 -0.230000 -6.700000 7165.860000 -0.230000 -6.800000 7448.420000 -0.280000 -7.200000 7742.120000 -0.210000 -7.000000 8047.400000 -0.220000 -8.600000 8364.720000 -0.320000 -8.600000 8694.540000 -0.330000 -9.600000 9037.380000 -0.460000 -9.700000 9393.730000 -0.460000 -10.000000 9764.140000 -0.640000 -11.000000 10149.100000 -0.710000 -11.000000 10549.300000 -0.890000 -12.000000 10965.300000 -0.960000 -12.000000 11397.700000 -1.110000 -12.000000 11847.100000 -1.230000 -12.000000 12314.300000 -1.350000 -12.000000 12799.800000 -1.520000 -12.000000 13304.500000 -1.630000 -12.000000 13829.100000 -1.810000 -11.000000 14374.400000 -1.860000 -11.000000 14941.200000 -2.020000 -11.000000 15530.400000 -2.200000 -11.000000 16142.800000 -2.410000 -11.000000 16779.300000 -2.560000 -9.800000 17440.900000 -2.670000 -8.600000 18128.600000 -2.790000 -7.600000 18843.500000 -2.920000 -6.300000 19586.500000 -3.050000 -4.800000 20358.800000 -3.120000 -3.000000 21161.600000 -3.150000 -1.100000 21996.000000 -3.130000 2.030000 22050.000000 -3.130000 2.030000 drc-3.2.2/source/mic/wm-61a.txt0000644000076400001450000000107711320622201015064 0ustar denisitadm0.000000000 0.000000000 20.00000000 0.000000000 1000.000000 0.000000000 2517.141803 0.017492711 3113.314539 0.052478134 4612.629425 0.332361516 5523.016651 0.402332362 6336.855612 0.717201166 7086.481211 1.032069971 7994.095078 1.311953353 9416.041127 1.521865889 10809.21183 1.696793003 11885.50042 1.871720117 13297.16535 1.906705539 14622.43000 1.836734694 15534.02143 1.591836735 16219.87756 1.416909621 17083.13416 1.241982507 18148.70088 0.997084548 19114.95738 0.612244898 19959.47147 0.367346939 20661.94465 0.192419825 21762.40932 0.157434402 22050.00000 0.157434402drc-3.2.2/source/mic/ecm8000.txt0000644000076400001450000000475411320622201015135 0ustar denisitadm00.0000 -0.07 31.9 20.0000 -0.07 31.9 25.1785 0.137 25.8 31.6978 0.275 20.2 39.9052 0.393 16.2 50.2377 0.344 12.3 63.2455 0.534 9.23 79.6214 0.512 6.47 100.237 0.493 4.27 126.191 0.358 3.03 158.865 0.407 0.06 200.000 0.114 -1.7 251.785 0.295 -3.1 300.640 0.204 -3.1 312.495 0.170 -3.4 324.817 0.136 -5.0 337.625 0.103 -4.2 350.938 0.073 -2.4 364.777 0.047 -3.6 379.160 0.021 -4.2 394.111 -0.00 -2.3 409.652 -0.01 -2.8 425.805 -0.01 -3.5 442.595 -0.01 -1.7 460.048 -0.02 -2.7 478.188 -0.02 -2.5 497.044 -0.02 -1.6 516.643 -0.02 -3.0 537.016 -0.02 -1.3 558.191 -0.03 -2.6 580.202 -0.04 -1.5 603.080 -0.05 -2.2 626.861 -0.06 -1.4 651.579 -0.06 -2.1 677.272 -0.07 -1.0 703.978 -0.07 -2.1 731.737 -0.08 -1.0 760.591 -0.09 -1.4 790.582 -0.11 -1.5 821.756 -0.12 -0.5 854.160 -0.12 -0.8 887.841 -0.11 -0.9 922.850 -0.08 -0.1 959.240 -0.04 0.22 997.064 -0.00 -0.1 1036.38 0.019 -0.5 1077.24 0.034 -0.8 1119.72 0.043 -0.7 1163.87 0.049 -0.7 1209.77 0.051 -0.8 1257.47 0.041 -1.1 1307.05 0.011 -1.3 1358.59 -0.04 -1.5 1412.17 -0.11 -1.2 1467.85 -0.15 -0.5 1525.73 -0.16 0.07 1585.89 -0.14 0.08 1648.43 -0.12 0.40 1713.43 -0.10 1.24 1780.99 -0.03 1.39 1851.22 0.116 2.27 1924.22 0.301 1.57 2000.09 0.448 0.89 2078.96 0.484 -0.4 2160.94 0.433 -1.8 2246.15 0.300 -2.8 2334.72 0.098 -3.3 2426.78 -0.17 -2.8 2522.47 -0.35 -1.4 2621.94 -0.41 0.85 2725.33 -0.14 3.37 2832.79 0.370 3.63 2944.49 0.682 1.43 3060.60 0.765 -1.4 3181.28 0.437 -3.8 3306.73 0.049 -3.7 3437.12 -0.23 -2.2 3572.65 -0.24 0.51 3713.53 0.035 2.42 3859.96 0.476 2.65 4012.16 0.803 0.25 4170.37 0.729 -2.8 4334.81 0.295 -4.1 4505.74 -0.01 -2.2 4683.41 0.072 0.40 4868.09 0.528 1.04 5060.05 0.747 -0.6 5259.57 0.813 -2.3 5466.97 0.653 -3.4 5682.54 0.589 -3.2 5906.61 0.635 -3.0 6139.52 0.763 -4.1 6381.62 0.624 -5.0 6633.25 0.475 -5.3 6894.82 0.428 -3.2 7166.69 0.978 -3.4 7449.29 1.015 -6.3 7743.03 0.913 -7.7 8048.35 0.764 -9.0 8365.71 0.691 -8.6 8695.58 0.767 -9.8 9038.47 0.588 -10.0 9394.87 0.590 -11.0 9765.33 0.493 -12.0 10150.3 0.390 -12.0 10550.6 0.464 -13.0 10966.6 0.245 -14.0 11399.1 0.180 -16.0 11848.5 -0.25 -16.0 12315.8 -0.13 -16.0 12801.4 -0.44 -17.0 13306.2 -0.44 -17.0 13830.9 -0.72 -18.0 14376.2 -0.82 -18.0 14943.1 -1.08 -20.0 15532.4 -1.29 -20.0 16144.8 -1.64 -21.0 16781.5 -1.90 -21.0 17443.2 -2.35 -21.0 18131.0 -2.70 -21.0 18845.9 -3.12 -21.0 19589.1 -3.57 -20.0 20361.5 -4.01 -18.0 21164.4 -4.46 -16.0 21999.0 -4.92 -15.0 22050.0 -4.92 -15.0drc-3.2.2/source/drc.layout0000644000076400001450000002131513165107243014564 0ustar denisitadm drc-3.2.2/source/cfgparse.cpp0000644000076400001450000002316513162156311015055 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Configuration file parsing utilities */ /* Inclusions */ #include "cfgparse.h" #include "boolean.h" #include "minIni/minIni.h" #include #include #include #include #include #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Configuration structure initialization */ static int CfgInit(const CfgParameter * CfgParameters) { int I; /* Cicle over the parameters list */ I = 0; while (CfgParameters[I].PType != CfgEnd) { /* Check the parameter type */ switch (CfgParameters[I].PType) { case CfgEnd: /* Should be impossible */ break; case CfgBoolean: *((Boolean *) CfgParameters[I].PValue) = False; break; case CfgString: *((char **) CfgParameters[I].PValue) = NULL; break; case CfgInt: *((int *) CfgParameters[I].PValue) = (int) 0; break; case CfgUInt: *((unsigned int *) CfgParameters[I].PValue) = (unsigned int) 0; break; case CfgLong: *((long *) CfgParameters[I].PValue) = (long) 0; break; case CfgULong: *((unsigned long *) CfgParameters[I].PValue) = (unsigned long) 0; break; case CfgFloat: *((float *) CfgParameters[I].PValue) = (float) 0.0; break; case CfgDouble: *((double *) CfgParameters[I].PValue) = (double) 0.0; break; } /* Next parameter */ I++; } /* Returns the parameter count */ return I; } /* Last error descritpion length */ #define CfgLastErrorDscLen 512 /* Last error descritpion */ static char CfgLastErrorDsc[CfgLastErrorDscLen]; /* Structure used to pass data to the callback procedure */ typedef struct { CfgFileType FType; CfgParameter * CfgParameters; int PCount; int PParsed; Boolean PError; } CfgCallbackInfoStruct; /* Parameter search function */ static int CfgPSearch(CfgParameter * CfgParameters, char * PKey) { int I; /* Cicle over the parameters list */ I = 0; while (CfgParameters[I].PType != CfgEnd) { if (strcmp(CfgParameters[I].PName,PKey) == 0) return I; /* Next parameter */ I++; } /* Parameter not found */ return I; } /* Configuration file parsing callback */ static int CfgCallback(const char * Section, const char * Key, const char * Value, const void * UserData) { /* Current callback informations */ CfgCallbackInfoStruct * CCI = (CfgCallbackInfoStruct *) UserData; /* Parameter search tmp buffer */ char PKey[INI_BUFFERSIZE]; /* Current parameter index */ int PI; /* Temporary variables */ char TB; long int TLI; unsigned long int TLU; float TF; double TD; char * TEP; /* Check if sections are allowed */ if (CCI->FType == CfgSimple) { /* Check that the section is empty */ if (Section[0] != '\0') { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Unexpected section '%s'.",Section); return (int) False; } /* Creates the search key */ snprintf(PKey,INI_BUFFERSIZE,"%s",Key); } else /* Creates the search key */ snprintf(PKey,INI_BUFFERSIZE,"%s:%s",Section,Key); /* Search the parameter */ PI = CfgPSearch(CCI->CfgParameters,PKey); /* Check if the parameter has been found */ if (PI == CCI->PCount) { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Unknown parameter '%s'.",PKey); return (int) False; } /* Parameter conversion */ switch (CCI->CfgParameters[PI].PType) { case CfgEnd: /* Should be impossible */ break; case CfgBoolean: TB = toupper(Value[0]); if (TB == 'T' || TB == 'Y' || TB == '1') { *((Boolean *) (CCI->CfgParameters[PI].PValue)) = True; return (int) True; } if (TB == 'F' || TB == 'N' || TB == '0') { *((Boolean *) (CCI->CfgParameters[PI].PValue)) = False; return (int) True; } CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Invalid boolean parameter '%s': %s.",PKey,Value); return (int) False; break; case CfgString: if((*((char **) (CCI->CfgParameters[PI].PValue)) = (char *) malloc(sizeof(char) * (1 + strlen(Value)))) == NULL) { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Parameter '%s' memory allocation failed.",PKey); return (int) False; } strcpy(*((char **) (CCI->CfgParameters[PI].PValue)),Value); break; case CfgInt: errno = 0; TLI = strtol(Value,&TEP,0); if (errno != 0 || Value[0] == '\0' || *TEP != '\0' || TLI > INT_MAX || TLI < INT_MIN) { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Invalid integer parameter '%s': %s.",PKey,Value); return (int) False; } *((int *) (CCI->CfgParameters[PI].PValue)) = (int) TLI; break; case CfgUInt: errno = 0; TLU = strtoul(Value,&TEP,0); if (errno != 0 || Value[0] == '\0' || *TEP != '\0' || TLU > UINT_MAX) { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Invalid integer parameter '%s': %s.",PKey,Value); return (int) False; } *((unsigned int *) (CCI->CfgParameters[PI].PValue)) = (unsigned int) TLU; break; case CfgLong: errno = 0; TLI = strtol(Value,&TEP,0); if (errno != 0 || Value[0] == '\0' || *TEP != '\0') { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Invalid integer parameter '%s': %s.",PKey,Value); return (int) False; } *((long *) (CCI->CfgParameters[PI].PValue)) = (long) TLI; break; case CfgULong: errno = 0; TLU = strtoul(Value,&TEP,0); if (errno != 0 || Value[0] == '\0' || *TEP != '\0' || TLU > UINT_MAX) { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Invalid integer parameter '%s': %s.",PKey,Value); return (int) False; } *((unsigned long *) (CCI->CfgParameters[PI].PValue)) = (unsigned long) TLU; break; case CfgFloat: errno = 0; TF = strtof(Value,&TEP); if (errno != 0 || Value[0] == '\0' || *TEP != '\0') { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Invalid floating point parameter '%s': %s.",PKey,Value); return (int) False; } *((float *) (CCI->CfgParameters[PI].PValue)) = (float) TF; break; case CfgDouble: errno = 0; TD = strtod(Value,&TEP); if (errno != 0 || Value[0] == '\0' || *TEP != '\0') { CCI->PError = True; snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Invalid floating point parameter '%s': %s.",PKey,Value); return (int) False; } *((double *) (CCI->CfgParameters[PI].PValue)) = (double) TD; break; } /* Increase the number of parameters parsed */ CCI->PParsed++; /* Conversion completed */ return (int) True; } /* Configuration parsing, return the number of parameters read or a negative value on error. */ int CfgParse(const char * CfgFile,CfgParameter * CfgParameters,const CfgFileType FType) { /* Callback information structure */ CfgCallbackInfoStruct CBInfo; /* Set the callback info structure */ CBInfo.FType = FType; CBInfo.CfgParameters = CfgParameters; CBInfo.PParsed = 0; CBInfo.PError = False; /* Parameter initialization and count */ CBInfo.PCount = CfgInit(CfgParameters); /* Reset the error description */ CfgLastErrorDsc[0] = '\0'; /* Parse the configuration file */ errno = 0; if (ini_browse(CfgCallback,(const void *) &CBInfo,CfgFile) == (int) False) { snprintf(CfgLastErrorDsc,CfgLastErrorDscLen,"Configuration file parsing error: %s.",strerror(errno)); return -1; } /* Check if there was a paring error */ if (CBInfo.PError == True) return -1; /* Parsing completed */ return CBInfo.PParsed; } /* Free the memory allocated by CfgParse */ void CfgFree(const CfgParameter * CfgParameters) { int I; /* Cicle over the parameters list */ I = 0; while (CfgParameters[I].PType != CfgEnd) { /* Check the parameter type */ if (CfgParameters[I].PType == CfgString && *((char **) CfgParameters[I].PValue) != NULL) free(*((char **) CfgParameters[I].PValue)); /* Next parameter */ I++; } } /* Get the last error descrition */ const char * CfgGetLastErrorDsc(void) { return CfgLastErrorDsc; } drc-3.2.2/source/fftsg_h.h0000644000076400001450000000172711320611736014351 0ustar denisitadm/* Fast Fourier/Cosine/Sine Transform Copyright Takuya OOURA, 1996-2001 (Email: ooura@kurims.kyoto-u.ac.jp or ooura@mmm.t.u-tokyo.ac.jp) You may use, copy, modify and distribute this code for any purpose (include commercial use) and without fee. http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html */ #ifndef fftsg_h_h #define fftsg_h_h #ifdef UseDouble /* Tipo floating point usato per le elaborazioni */ #define DLReal double #else /* Tipo floating point usato per le elaborazioni */ #define DLReal float #endif #ifdef __cplusplus extern "C" { #endif #define OouraForward (-1) #define OouraBackward (1) #define OouraRForward (1) #define OouraRBackward (-1) void cdft(int nx2, int dir, DLReal * data); void rdft(int n, int dir, DLReal * data); void ddct(int n, int dir, DLReal * data); void ddst(int n, int dir, DLReal * data); void dfct(int n, DLReal * data); void dfst(int n, DLReal * data); #ifdef __cplusplus } #endif #endif drc-3.2.2/source/dspwind.h0000644000076400001450000000445013162156312014375 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : DSPWind.h Autore : Sbragion Denis Descrizione : Funzioni per vari tipi di finestratura. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #ifndef DSPWind_h #define DSPWind_h #include "dsplib.h" // Tipo per finestrature parziali typedef enum { WLeft, WFull, WRight } WindowType; // Effettuano la finestratura dell' array A secondo la finestra // corrispondente al nome. void HammingWindow(DLReal * A,unsigned int Size); void HanningWindow(DLReal * A,unsigned int Size); void BlackmanWindow(DLReal * A,unsigned int Size); void BartlettWindow(DLReal * A,unsigned int Size); void BlackmanHarrisWindow(DLReal * A,unsigned int Size); void ExponentialWindow(DLReal * A,unsigned int Size,DLReal P = 2); // Finestratura parziale e spaziata void SpacedBlackmanWindow(DLReal * A,unsigned int Size, unsigned int Space, WindowType WType); void HalfBlackmanWindow(DLReal * A,unsigned int Size, unsigned int Space, WindowType WType); // Riempie A di 1. void Ones(DLReal * A,unsigned int Size); #endif /***************************************************************************/ drc-3.2.2/source/slprefilt.h0000644000076400001450000000326713162156312014736 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Prefiltratura a bande tramite sliding lowpass di un segnale */ #ifndef SLPreFilt_h #define SLPreFilt_h /* Inclusioni */ #include "dsplib.h" #include "dspwind.h" /* Tipo di curva parametrica da utilizzare */ typedef enum { SLPProportional, SLPBilinear } SLPPrefilteringType; /* Prefiltratura a bande tramite sliding lowpass di un segnale */ void SLPreFilt(DLReal * InImp, const int IBS, const int FBS, const int FilterLen, const int BandSplit, const DLReal WindowExponent, const int SampleFreq, const DLReal StartFreq, const DLReal EndFreq, int WindowGap, DLReal FSharpness, DLReal * OutImp, const WindowType WType, const SLPPrefilteringType SLPType); #endif drc-3.2.2/source/cmdline.cpp0000644000076400001450000002723713162156312014703 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2004 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@neomerica.it ****************************************************************************/ /* Command line parsing utilities */ /* Inclusioni */ #include "cmdline.h" #include #include #include #include #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Opzione help */ static char HelpSwitch[] = "help"; /* Effettua il conteggio degli elementi di una struttura ParseCfg */ static long GetCfgParametersCount(const CfgParameter * CfgParmsDef) { int I; I = 0; while (CfgParmsDef[I].PType != CfgEnd) I++; return I; } /* Registra le impostazioni per la command line a partire da una definizione ParseCfg. Torna una struttura opaque utilizzata per il recupero dei parametri dalla linea di comando. */ CmdLineType * RegisterCmdLine(const CfgParameter * CfgParmsDef) { int OptCount; CmdLineType * OptData; int I; /* Recupera il conteggio parametri */ OptCount = GetCfgParametersCount(CfgParmsDef); /* Alloca la struttura per i parametri della command line */ if ((OptData = (CmdLineType *) malloc(sizeof(CmdLineType))) == NULL) return NULL; if ((OptData->Options = (struct option *) malloc((OptCount + 2) * sizeof(struct option))) == NULL) { free(OptData); return NULL; } if ((OptData->Parms = (ParameterType *) malloc((OptCount + 1) * sizeof(ParameterType))) == NULL) { free(OptData->Options); free(OptData); return NULL; } if ((OptData->ParmSet = (Boolean *) malloc((OptCount + 1) * sizeof(Boolean))) == NULL) { free(OptData->Options); free(OptData->Parms); free(OptData); return NULL; } /* Registra il conteggio parametri */ OptData->OptCount = OptCount; /* Ciclo di impostazione dei parametri di configurazione */ for (I = 0;I < OptCount;I++) { /* Azzera il flag impostazione */ OptData->ParmSet[I] = False; /* Imposta il nome dell'opzione */ OptData->Options[I].name = CfgParmsDef[I].PName; /* Imposta il tipo argomento */ OptData->Options[I].has_arg = required_argument; /* Imposta i parametri facoltativi */ OptData->Options[I].flag = NULL; OptData->Options[I].val = 0; } /* Aggiunge l'opzione di help */ OptData->ParmSet[OptCount] = False; OptData->Options[OptCount].name = HelpSwitch; OptData->Options[OptCount].has_arg = no_argument; OptData->Options[OptCount].flag = NULL; OptData->Options[OptCount].val = 0; /* Chiude l'array opzioni */ OptData->Options[OptCount + 1].name = NULL; OptData->Options[OptCount + 1].has_arg = no_argument; OptData->Options[OptCount + 1].flag = NULL; OptData->Options[OptCount + 1].val = 0; /* Ritorna la struttura gestione command line */ return OptData; } /* String duplication */ static char * DString(const char * S) { char * DS; if ((DS = (char *) malloc(sizeof(char) * (1 + strlen(S)))) == NULL) return NULL; strcpy(DS,S); return DS; } /* Effettua il processing della command line */ int GetCmdLine(const int argc, char * const * argv, const CfgParameter * CfgParmsDef, CmdLineType * OptData, char ** CfgFileName) { int OptCount = OptData->OptCount; int OptInd; double FVal; long int LVal; char * CTail; int PRes = 0; int GORetCode; while((GORetCode = getopt_long(argc,argv,"",OptData->Options,&OptInd)) == 0) { /* Segnala il parametro come impostato */ OptData->ParmSet[OptInd] = True; /* Controlla se si tratta dell'opzione di help */ if (OptInd < OptCount) /* Verifica il tipo dell'opzione */ switch (CfgParmsDef[OptInd].PType) { /* Stringa */ case CfgString: /* Assegna il parametro */ if (optarg == NULL) OptData->Parms[OptInd].StrParm = NULL; else if (strlen(optarg) == 0) OptData->Parms[OptInd].StrParm = NULL; else OptData->Parms[OptInd].StrParm = DString(optarg); break; /* Intero */ case CfgInt: errno = 0; LVal = strtol(optarg,&CTail,0); if (errno != 0) { printf("Error parsing command line parameter '%s' with value '%s': %s\n", CfgParmsDef[OptInd].PName,optarg,strerror(errno)); fflush(stdout); OptData->ParmSet[OptInd] = False; LVal = 0; PRes = errno; } if (*CTail != '\0' || CTail == optarg) { printf("Command line parameter '%s' with value '%s' contains invalid characters.\n", CfgParmsDef[OptInd].PName,optarg); fflush(stdout); OptData->ParmSet[OptInd] = False; LVal = 0; PRes = EILSEQ; } if (LVal < INT_MIN || LVal > INT_MAX) { printf("Command line parameter '%s' with value '%s' is out of range.\n", CfgParmsDef[OptInd].PName,optarg); fflush(stdout); OptData->ParmSet[OptInd] = False; LVal = 0; PRes = EILSEQ; } OptData->Parms[OptInd].IntParm = LVal; break; /* Floating point */ case DRCCfgFloat: errno = 0; FVal = strtod(optarg,&CTail); if (errno != 0) { printf("Error parsing command line parameter '%s' with value '%s': %s\n", CfgParmsDef[OptInd].PName,optarg,strerror(errno)); fflush(stdout); OptData->ParmSet[OptInd] = False; FVal = 0.0; PRes = errno; } if (*CTail != '\0' || CTail == optarg) { printf("Command line parameter '%s' with value '%s' contains invalid characters.\n", CfgParmsDef[OptInd].PName,optarg); fflush(stdout); OptData->ParmSet[OptInd] = False; FVal = 0.0; PRes = EILSEQ; } if (FVal < -DRCMaxFloat || FVal > DRCMaxFloat) { printf("Command line parameter '%s' with value '%s' is out of range.\n", CfgParmsDef[OptInd].PName,optarg); fflush(stdout); OptData->ParmSet[OptInd] = False; FVal = 0.0; PRes = EILSEQ; } OptData->Parms[OptInd].FltParm = FVal; break; /* Parametri non supportati */ default: perror("\nGetCmdLine: invalid parameter type."); break; } } /* Verifica la condizione di uscita */ if (GORetCode != -1) return EINVAL; else { /* Recupera il nome del file */ if (optind < argc) *CfgFileName = DString(argv[optind]); else *CfgFileName = NULL; } return PRes; } /* Sovrascrive i parametri della definizione ParseCfg CfgParmsDef con i parametri recuperati dalla linea di comando e registrati nella in OptData. Recupera il nome del file di configurazione ponendolo in CfgFileName */ void CopyCmdLineParms(const CmdLineType * OptData,CfgParameter * CfgParmsDef) { int OptCount = OptData->OptCount; int I; /* Ciclo di impostazione dei parametri di configurazione */ for (I = 0;I < OptCount;I++) { /* Verifica se invocato a linea di comando */ if (OptData->ParmSet[I] == True) { /* Verifica il tipo del parametro */ switch (CfgParmsDef[I].PType) { /* Stringa */ case CfgString: /* Dealloca se presente */ if (*((void **) CfgParmsDef[I].PValue) != NULL) free(*((void **) CfgParmsDef[I].PValue)); /* Assegna il parametro */ if (OptData->Parms[I].StrParm == NULL) *((void **) CfgParmsDef[I].PValue) = NULL; else *((void **) CfgParmsDef[I].PValue) = (void *) DString(OptData->Parms[I].StrParm); break; /* Intero */ case CfgInt: *((int *) CfgParmsDef[I].PValue) = OptData->Parms[I].IntParm; break; /* Floating point */ case DRCCfgFloat: *((DRCFloat *) CfgParmsDef[I].PValue) = OptData->Parms[I].FltParm; break; /* Parametri non supportati */ default: perror("\nCopyCmdLineParms: invalid parameter type."); break; } } } } /* Visualizza le opzioni disponibili a linea di comando */ void ShowCmdLine(const CfgParameter * CfgParmsDef) { int I; /* Ciclo di visualizzazione dei parametri di configurazione */ I = 0; while (CfgParmsDef[I].PType != CfgEnd) { /* Verifica il tipo del parametro */ switch (CfgParmsDef[I].PType) { /* Stringa */ case CfgString: printf(" --%-28s \n",CfgParmsDef[I].PName); break; /* Intero */ case CfgInt: printf(" --%-28s \n",CfgParmsDef[I].PName); break; /* Floating point */ case DRCCfgFloat: printf(" --%-28s \n",CfgParmsDef[I].PName); break; /* Parametri non supportati */ default: perror("\nShowCmdLine: invalid parameter type."); break; } /* Passa al parametro successivo */ I++; } /* Svuota i buffer */ fflush(stdout); } /* Libera la memoria occupata per la gestione della command line */ void FreeCmdLine(CmdLineType * OptData, const CfgParameter * CfgParmsDef) { int OptCount = OptData->OptCount; int I; /* Ciclo di dellocazione dei parametri di configurazione */ for (I = 0;I < OptCount;I++) { /* Verifica se invocato a linea di comando */ if (OptData->ParmSet[I] == True) { /* Verifica il tipo del parametro */ switch (CfgParmsDef[I].PType) { /* Stringa */ case CfgString: /* Dealloca se presente */ if (OptData->Parms[I].StrParm != NULL) free(OptData->Parms[I].StrParm); break; /* Intero */ case CfgInt: break; /* Floating point */ case DRCCfgFloat: break; /* Parametri non supportati */ default: perror("\nFreeCmdLine: invalid parameter type."); break; } } } /* Dealloca la struttura dati */ free(OptData->Options); free(OptData->Parms); free(OptData->ParmSet); free(OptData); } /* Libera la memoria di una strttura di configurazione */ void FreeCfgParameters(CfgParameter * CfgParmsDef) { int OptCount; int I; /* Recupera il conteggio parametri */ OptCount = GetCfgParametersCount(CfgParmsDef); /* Ciclo di dellocazione dei parametri di configurazione */ for (I = 0;I < OptCount;I++) { /* Verifica il tipo del parametro */ switch (CfgParmsDef[I].PType) { /* Stringa */ case CfgString: /* Dealloca se presente */ if (*((void **) CfgParmsDef[I].PValue) != NULL) free(*((void **) CfgParmsDef[I].PValue)); break; /* Intero */ case CfgInt: break; /* Floating point */ case DRCCfgFloat: break; /* Parametri non supportati */ default: perror("\nFreeCfgParameters: invalid parameter type."); break; } } } drc-3.2.2/source/gsl/0000755000076400001450000000000013165107360013340 5ustar denisitadmdrc-3.2.2/source/gsl/factorize.c0000644000076400001450000000721712616157443015510 0ustar denisitadm/* fft/factorize.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "factorize.h" static int fft_complex_factorize (const size_t n, size_t *nf, size_t factors[]) { const size_t complex_subtransforms[] = {7, 6, 5, 4, 3, 2, 0}; /* other factors can be added here if their transform modules are implemented. The end of the list is marked by 0. */ int status = fft_factorize (n, complex_subtransforms, nf, factors); return status; } static int fft_halfcomplex_factorize (const size_t n, size_t *nf, size_t factors[]) { const size_t halfcomplex_subtransforms[] = {5, 4, 3, 2, 0}; int status = fft_factorize (n, halfcomplex_subtransforms, nf, factors); return status; } static int fft_real_factorize (const size_t n, size_t *nf, size_t factors[]) { const size_t real_subtransforms[] = {5, 4, 3, 2, 0}; int status = fft_factorize (n, real_subtransforms, nf, factors); return status; } static int fft_factorize (const size_t n, const size_t implemented_subtransforms[], size_t *n_factors, size_t factors[]) { size_t nf = 0; size_t ntest = n; size_t factor; size_t i = 0; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } if (n == 1) { factors[0] = 1; *n_factors = 1; return 0; } /* deal with the implemented factors first */ while (implemented_subtransforms[i] && ntest != 1) { factor = implemented_subtransforms[i]; while ((ntest % factor) == 0) { ntest = ntest / factor; factors[nf] = factor; nf++; } i++; } /* deal with any other even prime factors (there is only one) */ factor = 2; while ((ntest % factor) == 0 && (ntest != 1)) { ntest = ntest / factor; factors[nf] = factor; nf++; } /* deal with any other odd prime factors */ factor = 3; while (ntest != 1) { while ((ntest % factor) != 0) { factor += 2; } ntest = ntest / factor; factors[nf] = factor; nf++; } /* check that the factorization is correct */ { size_t product = 1; for (i = 0; i < nf; i++) { product *= factors[i]; } if (product != n) { GSL_ERROR ("factorization failed", GSL_ESANITY); } } *n_factors = nf; return 0; } static int fft_binary_logn (const size_t n) { size_t ntest ; size_t binary_logn = 0 ; size_t k = 1; while (k < n) { k *= 2; binary_logn++; } ntest = (1 << binary_logn) ; if (n != ntest ) { return -1 ; /* n is not a power of 2 */ } return binary_logn; } drc-3.2.2/source/gsl/gsl_fft_halfcomplex_float.h0000644000076400001450000000624212616157443020717 0ustar denisitadm/* fft/gsl_fft_halfcomplex_float.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_FFT_HALFCOMPLEX_FLOAT_H__ #define __GSL_FFT_HALFCOMPLEX_FLOAT_H__ #include #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS int gsl_fft_halfcomplex_float_radix2_backward (float data[], const size_t stride, const size_t n); int gsl_fft_halfcomplex_float_radix2_inverse (float data[], const size_t stride, const size_t n); int gsl_fft_halfcomplex_float_radix2_transform (float data[], const size_t stride, const size_t n); typedef struct { size_t n; size_t nf; size_t factor[64]; gsl_complex_float *twiddle[64]; gsl_complex_float *trig; } gsl_fft_halfcomplex_wavetable_float; gsl_fft_halfcomplex_wavetable_float * gsl_fft_halfcomplex_wavetable_float_alloc (size_t n); void gsl_fft_halfcomplex_wavetable_float_free (gsl_fft_halfcomplex_wavetable_float * wavetable); int gsl_fft_halfcomplex_float_backward (float data[], const size_t stride, const size_t n, const gsl_fft_halfcomplex_wavetable_float * wavetable, gsl_fft_real_workspace_float * work); int gsl_fft_halfcomplex_float_inverse (float data[], const size_t stride, const size_t n, const gsl_fft_halfcomplex_wavetable_float * wavetable, gsl_fft_real_workspace_float * work); int gsl_fft_halfcomplex_float_transform (float data[], const size_t stride, const size_t n, const gsl_fft_halfcomplex_wavetable_float * wavetable, gsl_fft_real_workspace_float * work); int gsl_fft_halfcomplex_float_unpack (const float halfcomplex_coefficient[], float complex_coefficient[], const size_t stride, const size_t n); int gsl_fft_halfcomplex_float_radix2_unpack (const float halfcomplex_coefficient[], float complex_coefficient[], const size_t stride, const size_t n); __END_DECLS #endif /* __GSL_FFT_HALFCOMPLEX_FLOAT_H__ */ drc-3.2.2/source/gsl/gsl_fft.h0000644000076400001450000000257212616157443015152 0ustar denisitadm/* fft/gsl_fft.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_FFT_H__ #define __GSL_FFT_H__ #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS typedef enum { gsl_fft_forward = -1, gsl_fft_backward = +1 } gsl_fft_direction; /* this gives the sign in the formula h(f) = \sum x(t) exp(+/- 2 pi i f t) where - is the forward transform direction and + the inverse direction */ __END_DECLS #endif /* __GSL_FFT_H__ */ drc-3.2.2/source/gsl/real_pass_2.c0000644000076400001450000000720612616157443015712 0ustar denisitadm/* fft/real_pass_2.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_real,pass_2) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]) { size_t k, k1; const size_t factor = 2; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1; const size_t from1 = from0 + m; const ATOMIC r0 = VECTOR(in,istride,from0); const ATOMIC r1 = VECTOR(in,istride,from1); const ATOMIC s0 = r0 + r1; const ATOMIC s1 = r0 - r1; const size_t to0 = product * k1; const size_t to1 = to0 + product - 1; VECTOR(out,ostride,to0) = s0; VECTOR(out,ostride,to1) = s1; } if (product_1 == 1) return; for (k = 1; k < (product_1 + 1) / 2; k++) { /* forward real transform: w -> conjugate(w) */ const ATOMIC w_real = GSL_REAL(twiddle[k - 1]); const ATOMIC w_imag = -GSL_IMAG(twiddle[k - 1]); for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + 2 * k - 1; const size_t from1 = from0 + m; const ATOMIC f0_real = VECTOR(in,istride,from0); const ATOMIC f0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC f1_real = VECTOR(in,istride,from1); const ATOMIC f1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC z0_real = f0_real; const ATOMIC z0_imag = f0_imag; const ATOMIC z1_real = w_real * f1_real - w_imag * f1_imag; const ATOMIC z1_imag = w_real * f1_imag + w_imag * f1_real; /* compute x = W(2) z */ /* x0 = z0 + z1 */ const ATOMIC x0_real = z0_real + z1_real; const ATOMIC x0_imag = z0_imag + z1_imag; /* x1 = z0 - z1 */ const ATOMIC x1_real = z0_real - z1_real; const ATOMIC x1_imag = z0_imag - z1_imag; const size_t to0 = k1 * product + 2 * k - 1; const size_t to1 = k1 * product + product - 2 * k - 1; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; /* stored in conjugate location */ VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to1 + 1) = -x1_imag; } } if (product_1 % 2 == 1) return; for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + product_1 - 1; const size_t from1 = from0 + m; const size_t to0 = k1 * product + product_1 - 1; VECTOR(out,ostride,to0) = VECTOR(in,istride,from0); VECTOR(out,ostride,to0 + 1) = -VECTOR(in,istride,from1); } return; } drc-3.2.2/source/gsl/templates_on.h0000644000076400001450000001443712616157443016223 0ustar denisitadm/* If BASE is undefined we use function names like gsl_name() and assume that we are using doubles. If BASE is defined we used function names like gsl_BASE_name() and use BASE as the base datatype */ #if defined(BASE_GSL_COMPLEX_LONG) #define BASE gsl_complex_long_double #define SHORT complex_long_double #define SHORT_REAL long_double #define ATOMIC long double #define USES_LONGDOUBLE 1 #define MULTIPLICITY 2 #define FP 1 #define IN_FORMAT "%Lg" #define OUT_FORMAT "%Lg" #define ATOMIC_IO ATOMIC #define ZERO {{0.0L,0.0L}} #define ONE {{1.0L,0.0L}} #define BASE_EPSILON GSL_DBL_EPSILON #elif defined(BASE_GSL_COMPLEX) #if defined(_MSC_VER) && defined(complex) #undef complex #endif #define BASE gsl_complex #define SHORT complex #define SHORT_REAL #define ATOMIC double #define MULTIPLICITY 2 #define FP 1 #define IN_FORMAT "%lg" #define OUT_FORMAT "%g" #define ATOMIC_IO ATOMIC #define ZERO {{0.0,0.0}} #define ONE {{1.0,0.0}} #define BASE_EPSILON GSL_DBL_EPSILON #elif defined(BASE_GSL_COMPLEX_FLOAT) #define BASE gsl_complex_float #define SHORT complex_float #define SHORT_REAL float #define ATOMIC float #define MULTIPLICITY 2 #define FP 1 #define IN_FORMAT "%g" #define OUT_FORMAT "%g" #define ATOMIC_IO ATOMIC #define ZERO {{0.0F,0.0F}} #define ONE {{1.0F,0.0F}} #define BASE_EPSILON GSL_FLT_EPSILON #elif defined(BASE_LONG_DOUBLE) #define BASE long double #define SHORT long_double #define ATOMIC long double #define USES_LONGDOUBLE 1 #define MULTIPLICITY 1 #define FP 1 #define IN_FORMAT "%Lg" #define OUT_FORMAT "%Lg" #define ATOMIC_IO ATOMIC #define ZERO 0.0L #define ONE 1.0L #define BASE_EPSILON GSL_DBL_EPSILON #elif defined(BASE_DOUBLE) #define BASE double #define SHORT #define ATOMIC double #define MULTIPLICITY 1 #define FP 1 #define IN_FORMAT "%lg" #define OUT_FORMAT "%g" #define ATOMIC_IO ATOMIC #define ZERO 0.0 #define ONE 1.0 #define BASE_EPSILON GSL_DBL_EPSILON #elif defined(BASE_FLOAT) #define BASE float #define SHORT float #define ATOMIC float #define MULTIPLICITY 1 #define FP 1 #define IN_FORMAT "%g" #define OUT_FORMAT "%g" #define ATOMIC_IO ATOMIC #define ZERO 0.0F #define ONE 1.0F #define BASE_EPSILON GSL_FLT_EPSILON #elif defined(BASE_ULONG) #define BASE unsigned long #define SHORT ulong #define ATOMIC unsigned long #define MULTIPLICITY 1 #define IN_FORMAT "%lu" #define OUT_FORMAT "%lu" #define ATOMIC_IO ATOMIC #define ZERO 0UL #define ONE 1UL #define UNSIGNED 1 #elif defined(BASE_LONG) #define BASE long #define SHORT long #define ATOMIC long #define MULTIPLICITY 1 #define IN_FORMAT "%ld" #define OUT_FORMAT "%ld" #define ATOMIC_IO ATOMIC #define ZERO 0L #define ONE 1L #elif defined(BASE_UINT) #define BASE unsigned int #define SHORT uint #define ATOMIC unsigned int #define MULTIPLICITY 1 #define IN_FORMAT "%u" #define OUT_FORMAT "%u" #define ATOMIC_IO ATOMIC #define ZERO 0U #define ONE 1U #define UNSIGNED 1 #elif defined(BASE_INT) #define BASE int #define SHORT int #define ATOMIC int #define MULTIPLICITY 1 #define IN_FORMAT "%d" #define OUT_FORMAT "%d" #define ATOMIC_IO ATOMIC #define ZERO 0 #define ONE 1 #elif defined(BASE_USHORT) #define BASE unsigned short #define SHORT ushort #define ATOMIC unsigned short #define MULTIPLICITY 1 #define IN_FORMAT "%hu" #define OUT_FORMAT "%hu" #define ATOMIC_IO ATOMIC #define ZERO 0U #define ONE 1U #define UNSIGNED 1 #elif defined(BASE_SHORT) #define BASE short #define SHORT short #define ATOMIC short #define MULTIPLICITY 1 #define IN_FORMAT "%hd" #define OUT_FORMAT "%hd" #define ATOMIC_IO ATOMIC #define ZERO 0 #define ONE 1 #elif defined(BASE_UCHAR) #define BASE unsigned char #define SHORT uchar #define ATOMIC unsigned char #define MULTIPLICITY 1 #define IN_FORMAT "%u" #define OUT_FORMAT "%u" #define ATOMIC_IO unsigned int #define ZERO 0U #define ONE 1U #define UNSIGNED 1 #elif defined(BASE_CHAR) #define BASE char #define SHORT char #define ATOMIC char #define MULTIPLICITY 1 #define IN_FORMAT "%d" #define OUT_FORMAT "%d" #define ATOMIC_IO int #define ZERO 0 #define ONE 1 #ifdef __CHAR_UNSIGNED__ #define UNSIGNED 1 #endif #else #error unknown BASE_ directive in source.h #endif #define CONCAT2x(a,b) a ## _ ## b #define CONCAT2(a,b) CONCAT2x(a,b) #define CONCAT3x(a,b,c) a ## _ ## b ## _ ## c #define CONCAT3(a,b,c) CONCAT3x(a,b,c) #define CONCAT4x(a,b,c,d) a ## _ ## b ## _ ## c ## _ ## d #define CONCAT4(a,b,c,d) CONCAT4x(a,b,c,d) #ifndef USE_QUALIFIER #define QUALIFIER #endif #ifdef USE_QUALIFIER #if defined(BASE_DOUBLE) #define FUNCTION(dir,name) CONCAT3(dir,QUALIFIER,name) #define TYPE(dir) dir #define VIEW(dir,name) CONCAT2(dir,name) #define QUALIFIED_TYPE(dir) QUALIFIER dir #define QUALIFIED_VIEW(dir,name) CONCAT3(dir,QUALIFIER,name) #else #define FUNCTION(a,c) CONCAT4(a,SHORT,QUALIFIER,c) #define TYPE(dir) CONCAT2(dir,SHORT) #define VIEW(dir,name) CONCAT3(dir,SHORT,name) #define QUALIFIED_TYPE(dir) QUALIFIER CONCAT2(dir,SHORT) #define QUALIFIED_VIEW(dir,name) CONCAT4(dir,SHORT,QUALIFIER,name) #endif #if defined(BASE_GSL_COMPLEX) #define REAL_TYPE(dir) dir #define REAL_VIEW(dir,name) CONCAT2(dir,name) #define QUALIFIED_REAL_TYPE(dir) QUALIFIER dir #define QUALIFIED_REAL_VIEW(dir,name) CONCAT3(dir,QUALIFIER,name) #else #define REAL_TYPE(dir) CONCAT2(dir,SHORT_REAL) #define REAL_VIEW(dir,name) CONCAT3(dir,SHORT_REAL,name) #define QUALIFIED_REAL_TYPE(dir) QUALIFIER CONCAT2(dir,SHORT_REAL) #define QUALIFIED_REAL_VIEW(dir,name) CONCAT4(dir,SHORT_REAL,QUALIFIER,name) #endif #else #if defined(BASE_DOUBLE) #define FUNCTION(dir,name) CONCAT2(dir,name) #define TYPE(dir) dir #define VIEW(dir,name) CONCAT2(dir,name) #define QUALIFIED_TYPE(dir) TYPE(dir) #define QUALIFIED_VIEW(dir,name) CONCAT2(dir,name) #else #define FUNCTION(a,c) CONCAT3(a,SHORT,c) #define TYPE(dir) CONCAT2(dir,SHORT) #define VIEW(dir,name) CONCAT3(dir,SHORT,name) #define QUALIFIED_TYPE(dir) TYPE(dir) #define QUALIFIED_VIEW(dir,name) CONCAT3(dir,SHORT,name) #endif #if defined(BASE_GSL_COMPLEX) #define REAL_TYPE(dir) dir #define REAL_VIEW(dir,name) CONCAT2(dir,name) #define QUALIFIED_REAL_TYPE(dir) dir #define QUALIFIED_REAL_VIEW(dir,name) CONCAT2(dir,name) #else #define REAL_TYPE(dir) CONCAT2(dir,SHORT_REAL) #define REAL_VIEW(dir,name) CONCAT3(dir,SHORT_REAL,name) #define QUALIFIED_REAL_TYPE(dir) CONCAT2(dir,SHORT_REAL) #define QUALIFIED_REAL_VIEW(dir,name) CONCAT3(dir,SHORT_REAL,name) #endif #endif #define STRING(x) #x #define EXPAND(x) STRING(x) #define NAME(x) EXPAND(TYPE(x)) drc-3.2.2/source/gsl/c_pass_7.c0000644000076400001450000003075312616157443015221 0ustar denisitadm/* fft/c_pass_7.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_7) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[], const TYPE(gsl_complex) twiddle5[], const TYPE(gsl_complex) twiddle6[]) { size_t i = 0, j = 0; size_t k, k1; const size_t factor = 7; const size_t m = n / factor; const size_t q = n / product; const size_t p_1 = product / factor; const size_t jump = (factor - 1) * p_1; const ATOMIC c1 = cos(1.0 * 2.0 * M_PI / 7.0) ; const ATOMIC c2 = cos(2.0 * 2.0 * M_PI / 7.0) ; const ATOMIC c3 = cos(3.0 * 2.0 * M_PI / 7.0) ; const ATOMIC s1 = sin(1.0 * 2.0 * M_PI / 7.0) ; const ATOMIC s2 = sin(2.0 * 2.0 * M_PI / 7.0) ; const ATOMIC s3 = sin(3.0 * 2.0 * M_PI / 7.0) ; for (k = 0; k < q; k++) { ATOMIC w1_real, w1_imag, w2_real, w2_imag, w3_real, w3_imag, w4_real, w4_imag, w5_real, w5_imag, w6_real, w6_imag; if (k == 0) { w1_real = 1.0; w1_imag = 0.0; w2_real = 1.0; w2_imag = 0.0; w3_real = 1.0; w3_imag = 0.0; w4_real = 1.0; w4_imag = 0.0; w5_real = 1.0; w5_imag = 0.0; w6_real = 1.0; w6_imag = 0.0; } else { if (sign == gsl_fft_forward) { /* forward tranform */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = GSL_IMAG(twiddle3[k - 1]); w4_real = GSL_REAL(twiddle4[k - 1]); w4_imag = GSL_IMAG(twiddle4[k - 1]); w5_real = GSL_REAL(twiddle5[k - 1]); w5_imag = GSL_IMAG(twiddle5[k - 1]); w6_real = GSL_REAL(twiddle6[k - 1]); w6_imag = GSL_IMAG(twiddle6[k - 1]); } else { /* backward tranform: w -> conjugate(w) */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = -GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = -GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = -GSL_IMAG(twiddle3[k - 1]); w4_real = GSL_REAL(twiddle4[k - 1]); w4_imag = -GSL_IMAG(twiddle4[k - 1]); w5_real = GSL_REAL(twiddle5[k - 1]); w5_imag = -GSL_IMAG(twiddle5[k - 1]); w6_real = GSL_REAL(twiddle6[k - 1]); w6_imag = -GSL_IMAG(twiddle6[k - 1]); } } for (k1 = 0; k1 < p_1; k1++) { const ATOMIC z0_real = REAL(in,istride,i); const ATOMIC z0_imag = IMAG(in,istride,i); const ATOMIC z1_real = REAL(in,istride,i+m); const ATOMIC z1_imag = IMAG(in,istride,i+m); const ATOMIC z2_real = REAL(in,istride,i+2*m); const ATOMIC z2_imag = IMAG(in,istride,i+2*m); const ATOMIC z3_real = REAL(in,istride,i+3*m); const ATOMIC z3_imag = IMAG(in,istride,i+3*m); const ATOMIC z4_real = REAL(in,istride,i+4*m); const ATOMIC z4_imag = IMAG(in,istride,i+4*m); const ATOMIC z5_real = REAL(in,istride,i+5*m); const ATOMIC z5_imag = IMAG(in,istride,i+5*m); const ATOMIC z6_real = REAL(in,istride,i+6*m); const ATOMIC z6_imag = IMAG(in,istride,i+6*m); /* compute x = W(7) z */ /* t0 = z1 + z6 */ const ATOMIC t0_real = z1_real + z6_real ; const ATOMIC t0_imag = z1_imag + z6_imag ; /* t1 = z1 - z6 */ const ATOMIC t1_real = z1_real - z6_real ; const ATOMIC t1_imag = z1_imag - z6_imag ; /* t2 = z2 + z5 */ const ATOMIC t2_real = z2_real + z5_real ; const ATOMIC t2_imag = z2_imag + z5_imag ; /* t3 = z2 - z5 */ const ATOMIC t3_real = z2_real - z5_real ; const ATOMIC t3_imag = z2_imag - z5_imag ; /* t4 = z4 + z3 */ const ATOMIC t4_real = z4_real + z3_real ; const ATOMIC t4_imag = z4_imag + z3_imag ; /* t5 = z4 - z3 */ const ATOMIC t5_real = z4_real - z3_real ; const ATOMIC t5_imag = z4_imag - z3_imag ; /* t6 = t2 + t0 */ const ATOMIC t6_real = t2_real + t0_real ; const ATOMIC t6_imag = t2_imag + t0_imag ; /* t7 = t5 + t3 */ const ATOMIC t7_real = t5_real + t3_real ; const ATOMIC t7_imag = t5_imag + t3_imag ; /* b0 = z0 + t6 + t4 */ const ATOMIC b0_real = z0_real + t6_real + t4_real ; const ATOMIC b0_imag = z0_imag + t6_imag + t4_imag ; /* b1 = ((cos(2pi/7) + cos(4pi/7) + cos(6pi/7))/3-1) (t6 + t4) */ const ATOMIC b1_real = (((c1 + c2 + c3)/3.0 - 1.0) * (t6_real + t4_real)); const ATOMIC b1_imag = (((c1 + c2 + c3)/3.0 - 1.0) * (t6_imag + t4_imag)); /* b2 = ((2*cos(2pi/7) - cos(4pi/7) - cos(6pi/7))/3) (t0 - t4) */ const ATOMIC b2_real = (((2.0 * c1 - c2 - c3)/3.0) * (t0_real - t4_real)); const ATOMIC b2_imag = (((2.0 * c1 - c2 - c3)/3.0) * (t0_imag - t4_imag)); /* b3 = ((cos(2pi/7) - 2*cos(4pi/7) + cos(6pi/7))/3) (t4 - t2) */ const ATOMIC b3_real = (((c1 - 2.0*c2 + c3)/3.0) * (t4_real - t2_real)); const ATOMIC b3_imag = (((c1 - 2.0*c2 + c3)/3.0) * (t4_imag - t2_imag)); /* b4 = ((cos(2pi/7) + cos(4pi/7) - 2*cos(6pi/7))/3) (t2 - t0) */ const ATOMIC b4_real = (((c1 + c2 - 2.0 * c3)/3.0) * (t2_real - t0_real)); const ATOMIC b4_imag = (((c1 + c2 - 2.0 * c3)/3.0) * (t2_imag - t0_imag)); /* b5 = sign * ((sin(2pi/7) + sin(4pi/7) - sin(6pi/7))/3) (t7 + t1) */ const ATOMIC b5_real = (-(int)sign) * ((s1 + s2 - s3)/3.0) * (t7_real + t1_real) ; const ATOMIC b5_imag = (-(int)sign) * ((s1 + s2 - s3)/3.0) * (t7_imag + t1_imag) ; /* b6 = sign * ((2sin(2pi/7) - sin(4pi/7) + sin(6pi/7))/3) (t1 - t5) */ const ATOMIC b6_real = (-(int)sign) * ((2.0 * s1 - s2 + s3)/3.0) * (t1_real - t5_real) ; const ATOMIC b6_imag = (-(int)sign) * ((2.0 * s1 - s2 + s3)/3.0) * (t1_imag - t5_imag) ; /* b7 = sign * ((sin(2pi/7) - 2sin(4pi/7) - sin(6pi/7))/3) (t5 - t3) */ const ATOMIC b7_real = (-(int)sign) * ((s1 - 2.0 * s2 - s3)/3.0) * (t5_real - t3_real) ; const ATOMIC b7_imag = (-(int)sign) * ((s1 - 2.0 * s2 - s3)/3.0) * (t5_imag - t3_imag) ; /* b8 = sign * ((sin(2pi/7) + sin(4pi/7) + 2sin(6pi/7))/3) (t3 - t1) */ const ATOMIC b8_real = (-(int)sign) * ((s1 + s2 + 2.0 * s3)/3.0) * (t3_real - t1_real) ; const ATOMIC b8_imag = (-(int)sign) * ((s1 + s2 + 2.0 * s3)/3.0) * (t3_imag - t1_imag) ; /* T0 = b0 + b1 */ const ATOMIC T0_real = b0_real + b1_real ; const ATOMIC T0_imag = b0_imag + b1_imag ; /* T1 = b2 + b3 */ const ATOMIC T1_real = b2_real + b3_real ; const ATOMIC T1_imag = b2_imag + b3_imag ; /* T2 = b4 - b3 */ const ATOMIC T2_real = b4_real - b3_real ; const ATOMIC T2_imag = b4_imag - b3_imag ; /* T3 = -b2 - b4 */ const ATOMIC T3_real = -b2_real - b4_real ; const ATOMIC T3_imag = -b2_imag - b4_imag ; /* T4 = b6 + b7 */ const ATOMIC T4_real = b6_real + b7_real ; const ATOMIC T4_imag = b6_imag + b7_imag ; /* T5 = b8 - b7 */ const ATOMIC T5_real = b8_real - b7_real ; const ATOMIC T5_imag = b8_imag - b7_imag ; /* T6 = -b8 - b6 */ const ATOMIC T6_real = -b8_real - b6_real ; const ATOMIC T6_imag = -b8_imag - b6_imag ; /* T7 = T0 + T1 */ const ATOMIC T7_real = T0_real + T1_real ; const ATOMIC T7_imag = T0_imag + T1_imag ; /* T8 = T0 + T2 */ const ATOMIC T8_real = T0_real + T2_real ; const ATOMIC T8_imag = T0_imag + T2_imag ; /* T9 = T0 + T3 */ const ATOMIC T9_real = T0_real + T3_real ; const ATOMIC T9_imag = T0_imag + T3_imag ; /* T10 = T4 + b5 */ const ATOMIC T10_real = T4_real + b5_real ; const ATOMIC T10_imag = T4_imag + b5_imag ; /* T11 = T5 + b5 */ const ATOMIC T11_real = T5_real + b5_real ; const ATOMIC T11_imag = T5_imag + b5_imag ; /* T12 = T6 + b5 */ const ATOMIC T12_real = T6_real + b5_real ; const ATOMIC T12_imag = T6_imag + b5_imag ; /* x0 = b0 */ const ATOMIC x0_real = b0_real ; const ATOMIC x0_imag = b0_imag ; /* x1 = T7 - i T10 */ const ATOMIC x1_real = T7_real + T10_imag ; const ATOMIC x1_imag = T7_imag - T10_real ; /* x2 = T9 - i T12 */ const ATOMIC x2_real = T9_real + T12_imag ; const ATOMIC x2_imag = T9_imag - T12_real ; /* x3 = T8 + i T11 */ const ATOMIC x3_real = T8_real - T11_imag ; const ATOMIC x3_imag = T8_imag + T11_real ; /* x4 = T8 - i T11 */ const ATOMIC x4_real = T8_real + T11_imag ; const ATOMIC x4_imag = T8_imag - T11_real ; /* x5 = T9 + i T12 */ const ATOMIC x5_real = T9_real - T12_imag ; const ATOMIC x5_imag = T9_imag + T12_real ; /* x6 = T7 + i T10 */ const ATOMIC x6_real = T7_real - T10_imag ; const ATOMIC x6_imag = T7_imag + T10_real ; /* apply twiddle factors */ /* to0 = 1 * x0 */ REAL(out,ostride,j) = x0_real; IMAG(out,ostride,j) = x0_imag; /* to1 = w1 * x1 */ REAL(out,ostride,j+p_1) = w1_real * x1_real - w1_imag * x1_imag; IMAG(out,ostride,j+p_1) = w1_real * x1_imag + w1_imag * x1_real; /* to2 = w2 * x2 */ REAL(out,ostride,j+2*p_1) = w2_real * x2_real - w2_imag * x2_imag; IMAG(out,ostride,j+2*p_1) = w2_real * x2_imag + w2_imag * x2_real; /* to3 = w3 * x3 */ REAL(out,ostride,j+3*p_1) = w3_real * x3_real - w3_imag * x3_imag; IMAG(out,ostride,j+3*p_1) = w3_real * x3_imag + w3_imag * x3_real; /* to4 = w4 * x4 */ REAL(out,ostride,j+4*p_1) = w4_real * x4_real - w4_imag * x4_imag; IMAG(out,ostride,j+4*p_1) = w4_real * x4_imag + w4_imag * x4_real; /* to5 = w5 * x5 */ REAL(out,ostride,j+5*p_1) = w5_real * x5_real - w5_imag * x5_imag; IMAG(out,ostride,j+5*p_1) = w5_real * x5_imag + w5_imag * x5_real; /* to6 = w6 * x6 */ REAL(out,ostride,j+6*p_1) = w6_real * x6_real - w6_imag * x6_imag; IMAG(out,ostride,j+6*p_1) = w6_real * x6_imag + w6_imag * x6_real; i++; j++; } j += jump; } return 0; } drc-3.2.2/source/gsl/hc_pass_3.c0000644000076400001450000001226113164706027015354 0ustar denisitadm/* fft/hc_pass_3.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_halfcomplex,pass_3) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[]) { size_t k, k1; size_t factor, q, m, product_1; ATOMIC tau = sqrt (3.0) / 2.0; factor = 3; m = n / factor; q = n / product; product_1 = product / factor; for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 3 * k1 * q; const size_t from1 = from0 + 2 * q - 1; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC t1_real = 2 * z1_real; const ATOMIC t2_real = z0_real - z1_real; const ATOMIC t3_imag = 2 * tau * z1_imag; const size_t to0 = q * k1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; VECTOR(out,ostride,to0) = z0_real + t1_real; VECTOR(out,ostride,to1) = t2_real - t3_imag; VECTOR(out,ostride,to2) = t2_real + t3_imag; } if (q == 1) return; for (k = 1; k < (q + 1) / 2; k++) { const ATOMIC w1_real = GSL_REAL(twiddle1[k - 1]); const ATOMIC w1_imag = GSL_IMAG(twiddle1[k - 1]); const ATOMIC w2_real = GSL_REAL(twiddle2[k - 1]); const ATOMIC w2_imag = GSL_IMAG(twiddle2[k - 1]); for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 3 * k1 * q + 2 * k - 1; const size_t from1 = from0 + 2 * q; const size_t from2 = 3 * k1 * q - 2 * k + 2 * q - 1; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC z2_imag = -VECTOR(in,istride,from2 + 1); /* compute x = W(3) z */ /* t1 = z1 + z2 */ const ATOMIC t1_real = z1_real + z2_real; const ATOMIC t1_imag = z1_imag + z2_imag; /* t2 = z0 - t1/2 */ const ATOMIC t2_real = z0_real - t1_real / 2.0; const ATOMIC t2_imag = z0_imag - t1_imag / 2.0; /* t3 = sin(pi/3)*(z1 - z2) */ const ATOMIC t3_real = tau * (z1_real - z2_real); const ATOMIC t3_imag = tau * (z1_imag - z2_imag); /* x0 = z0 + t1 */ const ATOMIC x0_real = z0_real + t1_real; const ATOMIC x0_imag = z0_imag + t1_imag; /* x1 = t2 + i t3 */ const ATOMIC x1_real = t2_real - t3_imag; const ATOMIC x1_imag = t2_imag + t3_real; /* x2 = t2 - i t3 */ const ATOMIC x2_real = t2_real + t3_imag; const ATOMIC x2_imag = t2_imag - t3_real; const size_t to0 = k1 * q + 2 * k - 1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; VECTOR(out,ostride,to1) = w1_real * x1_real - w1_imag * x1_imag; VECTOR(out,ostride,to1 + 1) = w1_imag * x1_real + w1_real * x1_imag; VECTOR(out,ostride,to2) = w2_real * x2_real - w2_imag * x2_imag; VECTOR(out,ostride,to2 + 1) = w2_imag * x2_real + w2_real * x2_imag; } } if (q % 2 == 1) return; for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 3 * k1 * q + q - 1; const size_t from1 = from0 + 2 * q; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC t1_real = z0_real - z1_real; const ATOMIC t2_real = 2 * tau * z0_imag; const ATOMIC x0_real = 2 * z0_real + z1_real; const ATOMIC x1_real = t1_real - t2_real; const ATOMIC x2_real = -t1_real - t2_real; const size_t to0 = k1 * q + q - 1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to2) = x2_real; } return; } drc-3.2.2/source/gsl/c_init.c0000644000076400001450000001131012616157443014754 0ustar denisitadm/* fft/c_init.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007, 2009 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ TYPE(gsl_fft_complex_wavetable) * FUNCTION(gsl_fft_complex_wavetable,alloc) (size_t n) { int status ; size_t i; size_t n_factors; size_t t, product, product_1, q; double d_theta; TYPE(gsl_fft_complex_wavetable) * wavetable ; if (n == 0) { GSL_ERROR_VAL ("length n must be positive integer", GSL_EDOM, 0); } wavetable = (TYPE(gsl_fft_complex_wavetable) *) malloc(sizeof(TYPE(gsl_fft_complex_wavetable))); if (wavetable == NULL) { GSL_ERROR_VAL ("failed to allocate struct", GSL_ENOMEM, 0); } wavetable->trig = (TYPE(gsl_complex) *) malloc (n * sizeof (TYPE(gsl_complex))); if (wavetable->trig == NULL) { free(wavetable) ; /* error in constructor, prevent memory leak */ GSL_ERROR_VAL ("failed to allocate trigonometric lookup table", GSL_ENOMEM, 0); } wavetable->n = n ; status = fft_complex_factorize (n, &n_factors, wavetable->factor); if (status) { /* exception in constructor, avoid memory leak */ free (wavetable->trig); free (wavetable); GSL_ERROR_VAL ("factorization failed", GSL_EFACTOR, 0); }; wavetable->nf = n_factors; d_theta = -2.0 * M_PI / ((double) n); t = 0; product = 1; for (i = 0; i < n_factors; i++) { size_t j; const size_t factor = wavetable->factor[i]; wavetable->twiddle[i] = wavetable->trig + t; product_1 = product; /* product_1 = p_(i-1) */ product *= factor; q = n / product; for (j = 1; j < factor; j++) { size_t k; size_t m = 0; for (k = 1; k <= q; k++) { double theta; m = m + j * product_1; m = m % n; theta = d_theta * m; /* d_theta*j*k*p_(i-1) */ GSL_REAL(wavetable->trig[t]) = cos (theta); GSL_IMAG(wavetable->trig[t]) = sin (theta); t++; } } } if (t > n) { /* exception in constructor, avoid memory leak */ free (wavetable->trig); free (wavetable); GSL_ERROR_VAL ("overflowed trigonometric lookup table", GSL_ESANITY, 0); } return wavetable; } TYPE(gsl_fft_complex_workspace) * FUNCTION(gsl_fft_complex_workspace,alloc) (size_t n) { TYPE(gsl_fft_complex_workspace) * workspace ; if (n == 0) { GSL_ERROR_VAL ("length n must be positive integer", GSL_EDOM, 0); } workspace = (TYPE(gsl_fft_complex_workspace) *) malloc(sizeof(TYPE(gsl_fft_complex_workspace))); if (workspace == NULL) { GSL_ERROR_VAL ("failed to allocate struct", GSL_ENOMEM, 0); } workspace->n = n ; workspace->scratch = (BASE *) malloc (2 * n * sizeof (BASE)); if (workspace->scratch == NULL) { free(workspace) ; /* error in constructor, prevent memory leak */ GSL_ERROR_VAL ("failed to allocate scratch space", GSL_ENOMEM, 0); } return workspace; } void FUNCTION(gsl_fft_complex_wavetable,free) (TYPE(gsl_fft_complex_wavetable) * wavetable) { RETURN_IF_NULL (wavetable); /* release trigonometric lookup tables */ free (wavetable->trig); wavetable->trig = NULL; free (wavetable) ; } void FUNCTION(gsl_fft_complex_workspace,free) (TYPE(gsl_fft_complex_workspace) * workspace) { RETURN_IF_NULL (workspace); /* release scratch space */ free (workspace->scratch); workspace->scratch = NULL; free (workspace) ; } int FUNCTION(gsl_fft_complex,memcpy) (TYPE(gsl_fft_complex_wavetable) * dest, TYPE(gsl_fft_complex_wavetable) * src) { int i, n, nf ; if (dest->n != src->n) { GSL_ERROR ("length of src and dest do not match", GSL_EINVAL); } n = dest->n ; nf = dest->nf ; memcpy(dest->trig, src->trig, n * sizeof (double)) ; for (i = 0 ; i < nf ; i++) { dest->twiddle[i] = dest->trig + (src->twiddle[i] - src->trig) ; } return 0 ; } drc-3.2.2/source/gsl/hc_pass_2.c0000644000076400001450000000627413164706006015357 0ustar denisitadm/* fft/hc_pass_2.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_halfcomplex,pass_2) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]) { size_t k, k1; size_t factor, q, m, product_1; factor = 2; m = n / factor; q = n / product; product_1 = product / factor; for (k1 = 0; k1 < product_1; k1++) { const ATOMIC r0 = VECTOR(in,istride,2 * k1 * q); const ATOMIC r1 = VECTOR(in,istride,2 * k1 * q + 2 * q - 1); const ATOMIC s0 = r0 + r1; const ATOMIC s1 = r0 - r1; VECTOR(out,ostride,q * k1) = s0; VECTOR(out,ostride,q * k1 + m) = s1; } if (q == 1) return; for (k = 1; k < (q + 1) / 2; k++) { const ATOMIC w_real = GSL_REAL(twiddle[k - 1]); const ATOMIC w_imag = GSL_IMAG(twiddle[k - 1]); for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 2 * k1 * q + 2 * k - 1; const size_t from1 = 2 * k1 * q - 2 * k + 2 * q - 1; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); /* compute x = W(2) z */ /* x0 = z0 + z1 */ const ATOMIC x0_real = z0_real + z1_real; const ATOMIC x0_imag = z0_imag - z1_imag; /* x1 = z0 - z1 */ const ATOMIC x1_real = z0_real - z1_real; const ATOMIC x1_imag = z0_imag + z1_imag; const size_t to0 = k1 * q + 2 * k - 1; const size_t to1 = to0 + m; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; VECTOR(out,ostride,to1) = w_real * x1_real - w_imag * x1_imag; VECTOR(out,ostride,to1 + 1) = w_imag * x1_real + w_real * x1_imag; } } if (q % 2 == 1) return; for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 2 * k1 * q + q - 1; const size_t to0 = k1 * q + q - 1; const size_t to1 = to0 + m; VECTOR(out,ostride,to0) = 2 * VECTOR(in,istride,from0); VECTOR(out,ostride,to1) = -2 * VECTOR(in,istride,from0 + 1); } return; } drc-3.2.2/source/gsl/bitreverse.c0000644000076400001450000000512013164711310015647 0ustar denisitadm/* fft/bitreverse.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include "complex_internal.h" #include "bitreverse.h" static int FUNCTION(fft_complex,bitreverse_order) (BASE data[], const size_t stride, const size_t n, size_t logn) { /* This is the Goldrader bit-reversal algorithm */ size_t i; size_t j = 0; logn = 0 ; /* not needed for this algorithm */ /* Get rid of unused argument warnings */ (void) logn; for (i = 0; i < n - 1; i++) { size_t k = n / 2 ; if (i < j) { const BASE tmp_real = REAL(data,stride,i); const BASE tmp_imag = IMAG(data,stride,i); REAL(data,stride,i) = REAL(data,stride,j); IMAG(data,stride,i) = IMAG(data,stride,j); REAL(data,stride,j) = tmp_real; IMAG(data,stride,j) = tmp_imag; } while (k <= j) { j = j - k ; k = k / 2 ; } j += k ; } return 0; } static int FUNCTION(fft_real,bitreverse_order) (BASE data[], const size_t stride, const size_t n, size_t logn) { /* This is the Goldrader bit-reversal algorithm */ size_t i; size_t j = 0; logn = 0 ; /* not needed for this algorithm */ /* Get rid of unused argument warnings */ (void) logn; for (i = 0; i < n - 1; i++) { size_t k = n / 2 ; if (i < j) { const BASE tmp = VECTOR(data,stride,i); VECTOR(data,stride,i) = VECTOR(data,stride,j); VECTOR(data,stride,j) = tmp; } while (k <= j) { j = j - k ; k = k / 2 ; } j += k ; } return 0; } drc-3.2.2/source/gsl/error.c0000644000076400001450000000407513164711217014644 0ustar denisitadm/* err/error.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include gsl_error_handler_t * gsl_error_handler = NULL; static void no_error_handler (const char *reason, const char *file, int line, int gsl_errno); void gsl_error (const char * reason, const char * file, int line, int gsl_errno) { if (gsl_error_handler) { (*gsl_error_handler) (reason, file, line, gsl_errno); return ; } gsl_stream_printf ("ERROR", file, line, reason); fflush (stdout); fprintf (stderr, "Default GSL error handler invoked.\n"); fflush (stderr); abort (); } gsl_error_handler_t * gsl_set_error_handler (gsl_error_handler_t * new_handler) { gsl_error_handler_t * previous_handler = gsl_error_handler; gsl_error_handler = new_handler; return previous_handler; } gsl_error_handler_t * gsl_set_error_handler_off (void) { gsl_error_handler_t * previous_handler = gsl_error_handler; gsl_error_handler = no_error_handler; return previous_handler; } static void no_error_handler (const char *reason, const char *file, int line, int gsl_errno) { /* do nothing */ /* Get rid of unused argument warnings */ (void) reason; (void) file; (void) line; (void) gsl_errno; return; } drc-3.2.2/source/gsl/gsl_math.h0000644000076400001450000001037112616157443015320 0ustar denisitadm/* gsl_math.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_MATH_H__ #define __GSL_MATH_H__ #include #include #include #include #include #include #include #include #ifndef M_E #define M_E 2.71828182845904523536028747135 /* e */ #endif #ifndef M_LOG2E #define M_LOG2E 1.44269504088896340735992468100 /* log_2 (e) */ #endif #ifndef M_LOG10E #define M_LOG10E 0.43429448190325182765112891892 /* log_10 (e) */ #endif #ifndef M_SQRT2 #define M_SQRT2 1.41421356237309504880168872421 /* sqrt(2) */ #endif #ifndef M_SQRT1_2 #define M_SQRT1_2 0.70710678118654752440084436210 /* sqrt(1/2) */ #endif #ifndef M_SQRT3 #define M_SQRT3 1.73205080756887729352744634151 /* sqrt(3) */ #endif #ifndef M_PI #define M_PI 3.14159265358979323846264338328 /* pi */ #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923132169164 /* pi/2 */ #endif #ifndef M_PI_4 #define M_PI_4 0.78539816339744830961566084582 /* pi/4 */ #endif #ifndef M_SQRTPI #define M_SQRTPI 1.77245385090551602729816748334 /* sqrt(pi) */ #endif #ifndef M_2_SQRTPI #define M_2_SQRTPI 1.12837916709551257389615890312 /* 2/sqrt(pi) */ #endif #ifndef M_1_PI #define M_1_PI 0.31830988618379067153776752675 /* 1/pi */ #endif #ifndef M_2_PI #define M_2_PI 0.63661977236758134307553505349 /* 2/pi */ #endif #ifndef M_LN10 #define M_LN10 2.30258509299404568401799145468 /* ln(10) */ #endif #ifndef M_LN2 #define M_LN2 0.69314718055994530941723212146 /* ln(2) */ #endif #ifndef M_LNPI #define M_LNPI 1.14472988584940017414342735135 /* ln(pi) */ #endif #ifndef M_EULER #define M_EULER 0.57721566490153286060651209008 /* Euler constant */ #endif #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS /* other needlessly compulsive abstractions */ #define GSL_IS_ODD(n) ((n) & 1) #define GSL_IS_EVEN(n) (!(GSL_IS_ODD(n))) #define GSL_SIGN(x) ((x) >= 0.0 ? 1 : -1) /* Return nonzero if x is a real number, i.e. non NaN or infinite. */ #define GSL_IS_REAL(x) (gsl_finite(x)) /* Definition of an arbitrary function with parameters */ struct gsl_function_struct { double (* function) (double x, void * params); void * params; }; typedef struct gsl_function_struct gsl_function ; #define GSL_FN_EVAL(F,x) (*((F)->function))(x,(F)->params) /* Definition of an arbitrary function returning two values, r1, r2 */ struct gsl_function_fdf_struct { double (* f) (double x, void * params); double (* df) (double x, void * params); void (* fdf) (double x, void * params, double * f, double * df); void * params; }; typedef struct gsl_function_fdf_struct gsl_function_fdf ; #define GSL_FN_FDF_EVAL_F(FDF,x) (*((FDF)->f))(x,(FDF)->params) #define GSL_FN_FDF_EVAL_DF(FDF,x) (*((FDF)->df))(x,(FDF)->params) #define GSL_FN_FDF_EVAL_F_DF(FDF,x,y,dy) (*((FDF)->fdf))(x,(FDF)->params,(y),(dy)) /* Definition of an arbitrary vector-valued function with parameters */ struct gsl_function_vec_struct { int (* function) (double x, double y[], void * params); void * params; }; typedef struct gsl_function_vec_struct gsl_function_vec ; #define GSL_FN_VEC_EVAL(F,x,y) (*((F)->function))(x,y,(F)->params) __END_DECLS #endif /* __GSL_MATH_H__ */ drc-3.2.2/source/gsl/gsl_sys.h0000644000076400001450000000364212616157443015210 0ustar denisitadm/* sys/gsl_sys.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_SYS_H__ #define __GSL_SYS_H__ #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS double gsl_log1p (const double x); double gsl_expm1 (const double x); double gsl_hypot (const double x, const double y); double gsl_hypot3 (const double x, const double y, const double z); double gsl_acosh (const double x); double gsl_asinh (const double x); double gsl_atanh (const double x); int gsl_isnan (const double x); int gsl_isinf (const double x); int gsl_finite (const double x); double gsl_nan (void); double gsl_posinf (void); double gsl_neginf (void); double gsl_fdiv (const double x, const double y); double gsl_coerce_double (const double x); float gsl_coerce_float (const float x); long double gsl_coerce_long_double (const long double x); double gsl_ldexp(const double x, const int e); double gsl_frexp(const double x, int * e); int gsl_fcmp (const double x1, const double x2, const double epsilon); __END_DECLS #endif /* __GSL_SYS_H__ */ drc-3.2.2/source/gsl/gsl_dft_complex_float.h0000644000076400001450000000347612616157443020070 0ustar denisitadm/* fft/gsl_dft_complex_float.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_DFT_COMPLEX_FLOAT_H__ #define __GSL_DFT_COMPLEX_FLOAT_H__ #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS int gsl_dft_complex_float_forward (const float data[], const size_t stride, const size_t n, float result[]); int gsl_dft_complex_float_backward (const float data[], const size_t stride, const size_t n, float result[]); int gsl_dft_complex_float_inverse (const float data[], const size_t stride, const size_t n, float result[]); int gsl_dft_complex_float_transform (const float data[], const size_t stride, const size_t n, float result[], const gsl_fft_direction sign); __END_DECLS #endif /* __GSL_DFT_COMPLEX_FLOAT_H__ */ drc-3.2.2/source/gsl/templates_off.h0000644000076400001450000000204112616157443016345 0ustar denisitadm#ifdef FUNCTION #undef FUNCTION #endif #ifdef CONCAT4 #undef CONCAT4 #endif #ifdef CONCAT4x #undef CONCAT4x #endif #ifdef CONCAT3 #undef CONCAT3 #endif #ifdef CONCAT3x #undef CONCAT3x #endif #ifdef CONCAT2 #undef CONCAT2 #endif #ifdef CONCAT2x #undef CONCAT2x #endif #ifdef TYPE #undef TYPE #endif #ifdef REAL_TYPE #undef REAL_TYPE #endif #ifdef QUALIFIED_TYPE #undef QUALIFIED_TYPE #endif #ifdef VIEW #undef VIEW #endif #ifdef REAL_VIEW #undef REAL_VIEW #endif #ifdef QUALIFIED_VIEW #undef QUALIFIED_VIEW #endif #ifdef QUALIFIED_REAL_TYPE #undef QUALIFIED_REAL_TYPE #endif #ifdef QUALIFIED_REAL_VIEW #undef QUALIFIED_REAL_VIEW #endif #ifdef USES_LONGDOUBLE #undef USES_LONGDOUBLE #endif #ifdef SHORT_REAL #undef SHORT_REAL #endif #ifndef USE_QUALIFIER #ifdef QUALIFIER #undef QUALIFIER #endif #endif #undef BASE #undef BASE_EPSILON #undef SHORT #undef ATOMIC #undef MULTIPLICITY #undef IN_FORMAT #undef OUT_FORMAT #undef ATOMIC_IO #undef ZERO #undef ONE #undef NAME #undef STRING #undef EXPAND #undef UNSIGNED #ifdef FP #undef FP #endif drc-3.2.2/source/gsl/hc_main.c0000644000076400001450000001213313164705626015112 0ustar denisitadm/* fft/hc_main.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "hc_pass.h" int FUNCTION(gsl_fft_halfcomplex,backward) (BASE data[], const size_t stride, const size_t n, const TYPE(gsl_fft_halfcomplex_wavetable) * wavetable, TYPE(gsl_fft_real_workspace) * work) { int status = FUNCTION(gsl_fft_halfcomplex,transform) (data, stride, n, wavetable, work) ; return status ; } int FUNCTION(gsl_fft_halfcomplex,inverse) (BASE data[], const size_t stride, const size_t n, const TYPE(gsl_fft_halfcomplex_wavetable) * wavetable, TYPE(gsl_fft_real_workspace) * work) { int status = FUNCTION(gsl_fft_halfcomplex,transform) (data, stride, n, wavetable, work); if (status) { return status; } /* normalize inverse fft with 1/n */ { const double norm = 1.0 / n; size_t i; for (i = 0; i < n; i++) { data[stride*i] *= norm; } } return status; } int FUNCTION(gsl_fft_halfcomplex,transform) (BASE data[], const size_t stride, const size_t n, const TYPE(gsl_fft_halfcomplex_wavetable) * wavetable, TYPE(gsl_fft_real_workspace) * work) { BASE * const scratch = work->scratch; BASE * in; BASE * out; size_t istride, ostride ; size_t factor, product, q; size_t i; size_t nf; int state; int tskip; TYPE(gsl_complex) *twiddle1, *twiddle2, *twiddle3, *twiddle4; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } if (n == 1) { /* FFT of one data point is the identity */ return 0; } if (n != wavetable->n) { GSL_ERROR ("wavetable does not match length of data", GSL_EINVAL); } if (n != work->n) { GSL_ERROR ("workspace does not match length of data", GSL_EINVAL); } nf = wavetable->nf; product = 1; state = 0; for (i = 0; i < nf; i++) { factor = wavetable->factor[i]; product *= factor; q = n / product; tskip = (q + 1) / 2 - 1; if (state == 0) { in = data; istride = stride; out = scratch; ostride = 1; state = 1; } else { in = scratch; istride = 1; out = data; ostride = stride; state = 0; } if (factor == 2) { twiddle1 = wavetable->twiddle[i]; FUNCTION(fft_halfcomplex,pass_2) (in, istride, out, ostride, product, n, twiddle1); } else if (factor == 3) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + tskip; FUNCTION(fft_halfcomplex,pass_3) (in, istride, out, ostride, product, n, twiddle1, twiddle2); } else if (factor == 4) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + tskip; twiddle3 = twiddle2 + tskip; FUNCTION(fft_halfcomplex,pass_4) (in, istride, out, ostride, product, n, twiddle1, twiddle2, twiddle3); } else if (factor == 5) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + tskip; twiddle3 = twiddle2 + tskip; twiddle4 = twiddle3 + tskip; FUNCTION(fft_halfcomplex,pass_5) (in, istride, out, ostride, product, n, twiddle1, twiddle2, twiddle3, twiddle4); } else { twiddle1 = wavetable->twiddle[i]; FUNCTION(fft_halfcomplex,pass_n) (in, istride, out, ostride, factor, product, n, twiddle1); } } if (state == 1) /* copy results back from scratch to data */ { for (i = 0; i < n; i++) { data[stride*i] = scratch[i] ; } } return 0; } drc-3.2.2/source/gsl/real_radix2.c0000644000076400001450000000727013164706154015713 0ustar denisitadm/* fft/real_radix2.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ int FUNCTION(gsl_fft_real,radix2_transform) (BASE data[], const size_t stride, const size_t n) { int result ; size_t p, p_1, q; size_t i; size_t logn = 0; int status; if (n == 1) /* identity operation */ { return 0 ; } /* make sure that n is a power of 2 */ result = fft_binary_logn(n) ; if (result == -1) { GSL_ERROR ("n is not a power of 2", GSL_EINVAL); } else { logn = result ; } /* bit reverse the ordering of input data for decimation in time algorithm */ status = FUNCTION(fft_real,bitreverse_order)(data, stride, n, logn) ; /* apply fft recursion */ p = 1; q = n ; for (i = 1; i <= logn; i++) { size_t a, b; p_1 = p ; p = 2 * p ; q = q / 2 ; /* a = 0 */ for (b = 0; b < q; b++) { ATOMIC t0_real = VECTOR(data,stride,b*p) + VECTOR(data,stride,b*p + p_1) ; ATOMIC t1_real = VECTOR(data,stride,b*p) - VECTOR(data,stride,b*p + p_1) ; VECTOR(data,stride,b*p) = t0_real ; VECTOR(data,stride,b*p + p_1) = t1_real ; } /* a = 1 ... p_{i-1}/2 - 1 */ { ATOMIC w_real = 1.0; ATOMIC w_imag = 0.0; const double theta = - 2.0 * M_PI / p; const ATOMIC s = sin (theta); const ATOMIC t = sin (theta / 2.0); const ATOMIC s2 = 2.0 * t * t; for (a = 1; a < (p_1)/2; a++) { /* trignometric recurrence for w-> exp(i theta) w */ { const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real; const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag; w_real = tmp_real; w_imag = tmp_imag; } for (b = 0; b < q; b++) { ATOMIC z0_real = VECTOR(data,stride,b*p + a) ; ATOMIC z0_imag = VECTOR(data,stride,b*p + p_1 - a) ; ATOMIC z1_real = VECTOR(data,stride,b*p + p_1 + a) ; ATOMIC z1_imag = VECTOR(data,stride,b*p + p - a) ; /* t0 = z0 + w * z1 */ ATOMIC t0_real = z0_real + w_real * z1_real - w_imag * z1_imag; ATOMIC t0_imag = z0_imag + w_real * z1_imag + w_imag * z1_real; /* t1 = z0 - w * z1 */ ATOMIC t1_real = z0_real - w_real * z1_real + w_imag * z1_imag; ATOMIC t1_imag = z0_imag - w_real * z1_imag - w_imag * z1_real; VECTOR(data,stride,b*p + a) = t0_real ; VECTOR(data,stride,b*p + p - a) = t0_imag ; VECTOR(data,stride,b*p + p_1 - a) = t1_real ; VECTOR(data,stride,b*p + p_1 + a) = -t1_imag ; } } } if (p_1 > 1) { for (b = 0; b < q; b++) { /* a = p_{i-1}/2 */ VECTOR(data,stride,b*p + p - p_1/2) *= -1 ; } } } return status; } drc-3.2.2/source/gsl/gsl_complex.h0000644000076400001450000000645612616157443016047 0ustar denisitadm/* complex/gsl_complex.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_COMPLEX_H__ #define __GSL_COMPLEX_H__ #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS /* two consecutive built-in types as a complex number */ typedef double * gsl_complex_packed ; typedef float * gsl_complex_packed_float ; typedef long double * gsl_complex_packed_long_double ; typedef const double * gsl_const_complex_packed ; typedef const float * gsl_const_complex_packed_float ; typedef const long double * gsl_const_complex_packed_long_double ; /* 2N consecutive built-in types as N complex numbers */ typedef double * gsl_complex_packed_array ; typedef float * gsl_complex_packed_array_float ; typedef long double * gsl_complex_packed_array_long_double ; typedef const double * gsl_const_complex_packed_array ; typedef const float * gsl_const_complex_packed_array_float ; typedef const long double * gsl_const_complex_packed_array_long_double ; /* Yes... this seems weird. Trust us. The point is just that sometimes you want to make it obvious that something is an output value. The fact that it lacks a 'const' may not be enough of a clue for people in some contexts. */ typedef double * gsl_complex_packed_ptr ; typedef float * gsl_complex_packed_float_ptr ; typedef long double * gsl_complex_packed_long_double_ptr ; typedef const double * gsl_const_complex_packed_ptr ; typedef const float * gsl_const_complex_packed_float_ptr ; typedef const long double * gsl_const_complex_packed_long_double_ptr ; typedef struct { long double dat[2]; } gsl_complex_long_double; typedef struct { double dat[2]; } gsl_complex; typedef struct { float dat[2]; } gsl_complex_float; #define GSL_REAL(z) ((z).dat[0]) #define GSL_IMAG(z) ((z).dat[1]) #define GSL_COMPLEX_P(zp) ((zp)->dat) #define GSL_COMPLEX_P_REAL(zp) ((zp)->dat[0]) #define GSL_COMPLEX_P_IMAG(zp) ((zp)->dat[1]) #define GSL_COMPLEX_EQ(z1,z2) (((z1).dat[0] == (z2).dat[0]) && ((z1).dat[1] == (z2).dat[1])) #define GSL_SET_COMPLEX(zp,x,y) do {(zp)->dat[0]=(x); (zp)->dat[1]=(y);} while(0) #define GSL_SET_REAL(zp,x) do {(zp)->dat[0]=(x);} while(0) #define GSL_SET_IMAG(zp,y) do {(zp)->dat[1]=(y);} while(0) #define GSL_SET_COMPLEX_PACKED(zp,n,x,y) do {*((zp)+2*(n))=(x); *((zp)+(2*(n)+1))=(y);} while(0) __END_DECLS #endif /* __GSL_COMPLEX_H__ */ drc-3.2.2/source/gsl/gsl_fft_real.h0000644000076400001450000000427012616157443016152 0ustar denisitadm/* fft/gsl_fft_real.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_FFT_REAL_H__ #define __GSL_FFT_REAL_H__ #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS int gsl_fft_real_radix2_transform (double data[], const size_t stride, const size_t n) ; typedef struct { size_t n; size_t nf; size_t factor[64]; gsl_complex *twiddle[64]; gsl_complex *trig; } gsl_fft_real_wavetable; typedef struct { size_t n; double *scratch; } gsl_fft_real_workspace; gsl_fft_real_wavetable * gsl_fft_real_wavetable_alloc (size_t n); void gsl_fft_real_wavetable_free (gsl_fft_real_wavetable * wavetable); gsl_fft_real_workspace * gsl_fft_real_workspace_alloc (size_t n); void gsl_fft_real_workspace_free (gsl_fft_real_workspace * workspace); int gsl_fft_real_transform (double data[], const size_t stride, const size_t n, const gsl_fft_real_wavetable * wavetable, gsl_fft_real_workspace * work); int gsl_fft_real_unpack (const double real_coefficient[], double complex_coefficient[], const size_t stride, const size_t n); __END_DECLS #endif /* __GSL_FFT_REAL_H__ */ drc-3.2.2/source/gsl/gsl_fft.c0000644000076400001450000000465012616157443015144 0ustar denisitadm#include #include #include #include #include #include #include #include #include #define BASE_DOUBLE #include "templates_on.h" #include "bitreverse.c" #include "templates_off.h" #undef BASE_DOUBLE #define BASE_FLOAT #include "templates_on.h" #include "bitreverse.c" #include "templates_off.h" #undef BASE_FLOAT #include "factorize.c" #define BASE_DOUBLE #include "templates_on.h" #include "c_init.c" #include "c_main.c" #include "c_pass_2.c" #include "c_pass_3.c" #include "c_pass_4.c" #include "c_pass_5.c" #include "c_pass_6.c" #include "c_pass_7.c" #include "c_pass_n.c" #include "c_radix2.c" #include "templates_off.h" #undef BASE_DOUBLE #define BASE_FLOAT #include "templates_on.h" #include "c_init.c" #include "c_main.c" #include "c_pass_2.c" #include "c_pass_3.c" #include "c_pass_4.c" #include "c_pass_5.c" #include "c_pass_6.c" #include "c_pass_7.c" #include "c_pass_n.c" #include "c_radix2.c" #include "templates_off.h" #undef BASE_FLOAT #include #include #define BASE_DOUBLE #include "templates_on.h" #include "hc_init.c" #include "hc_main.c" #include "hc_pass_2.c" #include "hc_pass_3.c" #include "hc_pass_4.c" #include "hc_pass_5.c" #include "hc_pass_n.c" #include "hc_radix2.c" #include "hc_unpack.c" #include "templates_off.h" #undef BASE_DOUBLE #define BASE_FLOAT #include "templates_on.h" #include "hc_init.c" #include "hc_main.c" #include "hc_pass_2.c" #include "hc_pass_3.c" #include "hc_pass_4.c" #include "hc_pass_5.c" #include "hc_pass_n.c" #include "hc_radix2.c" #include "hc_unpack.c" #include "templates_off.h" #undef BASE_FLOAT #include #include #define BASE_DOUBLE #include "templates_on.h" #include "real_init.c" #include "real_main.c" #include "real_pass_2.c" #include "real_pass_3.c" #include "real_pass_4.c" #include "real_pass_5.c" #include "real_pass_n.c" #include "real_radix2.c" #include "real_unpack.c" #include "templates_off.h" #undef BASE_DOUBLE #define BASE_FLOAT #include "templates_on.h" #include "real_init.c" #include "real_main.c" #include "real_pass_2.c" #include "real_pass_3.c" #include "real_pass_4.c" #include "real_pass_5.c" #include "real_pass_n.c" #include "real_radix2.c" #include "real_unpack.c" #include "templates_off.h" #undef BASE_FLOAT drc-3.2.2/source/gsl/stream.c0000644000076400001450000000345712616157443015017 0ustar denisitadm/* err/stream.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include FILE * gsl_stream = NULL ; gsl_stream_handler_t * gsl_stream_handler = NULL; void gsl_stream_printf (const char *label, const char *file, int line, const char *reason) { if (gsl_stream == NULL) { gsl_stream = stderr; } if (gsl_stream_handler) { (*gsl_stream_handler) (label, file, line, reason); return; } fprintf (gsl_stream, "gsl: %s:%d: %s: %s\n", file, line, label, reason); } gsl_stream_handler_t * gsl_set_stream_handler (gsl_stream_handler_t * new_handler) { gsl_stream_handler_t * previous_handler = gsl_stream_handler; gsl_stream_handler = new_handler; return previous_handler; } FILE * gsl_set_stream (FILE * new_stream) { FILE * previous_stream; if (gsl_stream == NULL) { gsl_stream = stderr; } previous_stream = gsl_stream; gsl_stream = new_stream; return previous_stream; } drc-3.2.2/source/gsl/hc_pass_n.c0000644000076400001450000002006512616157443015453 0ustar denisitadm/* fft/hc_pass_n.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_halfcomplex,pass_n) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t factor, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]) { size_t k, k1; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; size_t e1, e2; const double d_theta = 2.0 * M_PI / ((double) factor); const ATOMIC cos_d_theta = cos (d_theta); const ATOMIC sin_d_theta = sin (d_theta); for (k1 = 0; k1 < product_1; k1++) { /* compute z = W(factor) x, for x halfcomplex */ ATOMIC dw_real = 1.0, dw_imag = 0.0; for (e1 = 0; e1 < factor; e1++) { ATOMIC sum_real = 0.0; ATOMIC w_real = 1.0, w_imag = 0.0; if (e1 > 0) { ATOMIC tmp_real = dw_real * cos_d_theta - dw_imag * sin_d_theta; ATOMIC tmp_imag = dw_real * sin_d_theta + dw_imag * cos_d_theta; dw_real = tmp_real; dw_imag = tmp_imag; } for (e2 = 0; e2 <= factor - e2; e2++) { ATOMIC z_real, z_imag; if (e2 > 0) { ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag; ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real; w_real = tmp_real; w_imag = tmp_imag; } if (e2 == 0) { size_t from_idx = factor * k1 * q; z_real = VECTOR(in,istride,from_idx); z_imag = 0.0; sum_real += w_real * z_real - w_imag * z_imag; } else if (e2 == factor - e2) { size_t from_idx = factor * q * k1 + 2 * e2 * q - 1; z_real = VECTOR(in,istride,from_idx); z_imag = 0.0; sum_real += w_real * z_real; } else { size_t from_idx = factor * q * k1 + 2 * e2 * q - 1; z_real = VECTOR(in,istride,from_idx); z_imag = VECTOR(in,istride,from_idx + 1); sum_real += 2 * (w_real * z_real - w_imag * z_imag); } } { const size_t to_idx = q * k1 + e1 * m; VECTOR(out,ostride,to_idx) = sum_real; } } } if (q == 1) return; for (k = 1; k < (q + 1) / 2; k++) { for (k1 = 0; k1 < product_1; k1++) { ATOMIC dw_real = 1.0, dw_imag = 0.0; for (e1 = 0; e1 < factor; e1++) { ATOMIC z_real, z_imag; ATOMIC sum_real = 0.0; ATOMIC sum_imag = 0.0; ATOMIC w_real = 1.0, w_imag = 0.0; if (e1 > 0) { ATOMIC t_real = dw_real * cos_d_theta - dw_imag * sin_d_theta; ATOMIC t_imag = dw_real * sin_d_theta + dw_imag * cos_d_theta; dw_real = t_real; dw_imag = t_imag; } for (e2 = 0; e2 < factor; e2++) { if (e2 > 0) { ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag; ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real; w_real = tmp_real; w_imag = tmp_imag; } if (e2 < factor - e2) { const size_t from0 = factor * k1 * q + 2 * k + 2 * e2 * q - 1; z_real = VECTOR(in,istride,from0); z_imag = VECTOR(in,istride,from0 + 1); } else { const size_t from0 = factor * k1 * q - 2 * k + 2 * (factor - e2) * q - 1; z_real = VECTOR(in,istride,from0); z_imag = -VECTOR(in,istride,from0 + 1); } sum_real += w_real * z_real - w_imag * z_imag; sum_imag += w_real * z_imag + w_imag * z_real; } if (k == 0 || e1 == 0) { w_real = 1.0; w_imag = 0.0; } else { size_t tskip = (q + 1) / 2 - 1; w_real = GSL_REAL(twiddle[k - 1 + tskip * (e1 - 1)]); w_imag = GSL_IMAG(twiddle[k - 1 + tskip * (e1 - 1)]); } { const size_t to0 = k1 * q + 2 * k + e1 * m - 1; VECTOR(out,ostride,to0) = w_real * sum_real - w_imag * sum_imag; VECTOR(out,ostride,to0 + 1) = w_real * sum_imag + w_imag * sum_real; } } } } if (q % 2 == 1) return; { double tw_arg = M_PI / ((double) factor); ATOMIC cos_tw_arg = cos (tw_arg); ATOMIC sin_tw_arg = sin (tw_arg); for (k1 = 0; k1 < product_1; k1++) { ATOMIC dw_real = 1.0, dw_imag = 0.0; ATOMIC tw_real = 1.0, tw_imag = 0.0; for (e1 = 0; e1 < factor; e1++) { ATOMIC w_real, w_imag, z_real, z_imag; ATOMIC sum_real = 0.0; if (e1 > 0) { ATOMIC tmp_real = tw_real * cos_tw_arg - tw_imag * sin_tw_arg; ATOMIC tmp_imag = tw_real * sin_tw_arg + tw_imag * cos_tw_arg; tw_real = tmp_real; tw_imag = tmp_imag; } w_real = tw_real; w_imag = tw_imag; if (e1 > 0) { ATOMIC t_real = dw_real * cos_d_theta - dw_imag * sin_d_theta; ATOMIC t_imag = dw_real * sin_d_theta + dw_imag * cos_d_theta; dw_real = t_real; dw_imag = t_imag; } for (e2 = 0; e2 <= factor - e2 - 1; e2++) { if (e2 > 0) { ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag; ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real; w_real = tmp_real; w_imag = tmp_imag; } if (e2 == factor - e2 - 1) { const size_t from0 = factor * k1 * q + q + 2 * e2 * q - 1; z_real = VECTOR(in,istride,from0); z_imag = 0.0; sum_real += w_real * z_real - w_imag * z_imag; } else { const size_t from0 = factor * k1 * q + q + 2 * e2 * q - 1; z_real = VECTOR(in,istride,from0); z_imag = VECTOR(in,istride,from0 + 1); sum_real += 2 * (w_real * z_real - w_imag * z_imag); } } { const size_t to0 = k1 * q + q + e1 * m - 1; VECTOR(out,ostride,to0) = sum_real; } } } } return; } drc-3.2.2/source/gsl/gsl_nan.h0000644000076400001450000000246712616157443015152 0ustar denisitadm/* gsl_nan.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_NAN_H__ #define __GSL_NAN_H__ #ifdef INFINITY # define GSL_POSINF INFINITY # define GSL_NEGINF (-INFINITY) #elif defined(HUGE_VAL) # define GSL_POSINF HUGE_VAL # define GSL_NEGINF (-HUGE_VAL) #else # define GSL_POSINF (gsl_posinf()) # define GSL_NEGINF (gsl_neginf()) #endif #ifdef NAN # define GSL_NAN NAN #elif defined(INFINITY) # define GSL_NAN (INFINITY/INFINITY) #else # define GSL_NAN (gsl_nan()) #endif #define GSL_POSZERO (+0.0) #define GSL_NEGZERO (-0.0) #endif /* __GSL_NAN_H__ */ drc-3.2.2/source/gsl/c_radix2.c0000644000076400001450000002034513164705550015207 0ustar denisitadm/* fft/c_radix2.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ int FUNCTION(gsl_fft_complex,radix2_forward) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n) { gsl_fft_direction sign = gsl_fft_forward; int status = FUNCTION(gsl_fft_complex,radix2_transform) (data, stride, n, sign); return status; } int FUNCTION(gsl_fft_complex,radix2_backward) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n) { gsl_fft_direction sign = gsl_fft_backward; int status = FUNCTION(gsl_fft_complex,radix2_transform) (data, stride, n, sign); return status; } int FUNCTION(gsl_fft_complex,radix2_inverse) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n) { gsl_fft_direction sign = gsl_fft_backward; int status = FUNCTION(gsl_fft_complex,radix2_transform) (data, stride, n, sign); if (status) { return status; } /* normalize inverse fft with 1/n */ { const ATOMIC norm = 1.0 / n; size_t i; for (i = 0; i < n; i++) { REAL(data,stride,i) *= norm; IMAG(data,stride,i) *= norm; } } return status; } int FUNCTION(gsl_fft_complex,radix2_transform) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n, const gsl_fft_direction sign) { int result ; size_t dual; size_t bit; size_t logn = 0; int status; if (n == 1) /* identity operation */ { return 0 ; } /* make sure that n is a power of 2 */ result = fft_binary_logn(n) ; if (result == -1) { GSL_ERROR ("n is not a power of 2", GSL_EINVAL); } else { logn = result ; } /* bit reverse the ordering of input data for decimation in time algorithm */ status = FUNCTION(fft_complex,bitreverse_order) (data, stride, n, logn) ; /* apply fft recursion */ dual = 1; for (bit = 0; bit < logn; bit++) { ATOMIC w_real = 1.0; ATOMIC w_imag = 0.0; const double theta = 2.0 * ((int) sign) * M_PI / (2.0 * (double) dual); const ATOMIC s = sin (theta); const ATOMIC t = sin (theta / 2.0); const ATOMIC s2 = 2.0 * t * t; size_t a, b; /* a = 0 */ for (b = 0; b < n; b += 2 * dual) { const size_t i = b ; const size_t j = b + dual; const ATOMIC z1_real = REAL(data,stride,j) ; const ATOMIC z1_imag = IMAG(data,stride,j) ; const ATOMIC wd_real = z1_real ; const ATOMIC wd_imag = z1_imag ; REAL(data,stride,j) = REAL(data,stride,i) - wd_real; IMAG(data,stride,j) = IMAG(data,stride,i) - wd_imag; REAL(data,stride,i) += wd_real; IMAG(data,stride,i) += wd_imag; } /* a = 1 .. (dual-1) */ for (a = 1; a < dual; a++) { /* trignometric recurrence for w-> exp(i theta) w */ { const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real; const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag; w_real = tmp_real; w_imag = tmp_imag; } for (b = 0; b < n; b += 2 * dual) { const size_t i = b + a; const size_t j = b + a + dual; const ATOMIC z1_real = REAL(data,stride,j) ; const ATOMIC z1_imag = IMAG(data,stride,j) ; const ATOMIC wd_real = w_real * z1_real - w_imag * z1_imag; const ATOMIC wd_imag = w_real * z1_imag + w_imag * z1_real; REAL(data,stride,j) = REAL(data,stride,i) - wd_real; IMAG(data,stride,j) = IMAG(data,stride,i) - wd_imag; REAL(data,stride,i) += wd_real; IMAG(data,stride,i) += wd_imag; } } dual *= 2; } return status; } int FUNCTION(gsl_fft_complex,radix2_dif_forward) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n) { gsl_fft_direction sign = gsl_fft_forward; int status = FUNCTION(gsl_fft_complex,radix2_dif_transform) (data, stride, n, sign); return status; } int FUNCTION(gsl_fft_complex,radix2_dif_backward) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n) { gsl_fft_direction sign = gsl_fft_backward; int status = FUNCTION(gsl_fft_complex,radix2_dif_transform) (data, stride, n, sign); return status; } int FUNCTION(gsl_fft_complex,radix2_dif_inverse) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n) { gsl_fft_direction sign = gsl_fft_backward; int status = FUNCTION(gsl_fft_complex,radix2_dif_transform) (data, stride, n, sign); if (status) { return status; } /* normalize inverse fft with 1/n */ { const ATOMIC norm = 1.0 / n; size_t i; for (i = 0; i < n; i++) { REAL(data,stride,i) *= norm; IMAG(data,stride,i) *= norm; } } return status; } int FUNCTION(gsl_fft_complex,radix2_dif_transform) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n, const gsl_fft_direction sign) { int result ; size_t dual; size_t bit; size_t logn = 0; int status; if (n == 1) /* identity operation */ { return 0 ; } /* make sure that n is a power of 2 */ result = fft_binary_logn(n) ; if (result == -1) { GSL_ERROR ("n is not a power of 2", GSL_EINVAL); } else { logn = result ; } /* apply fft recursion */ dual = n / 2; for (bit = 0; bit < logn; bit++) { ATOMIC w_real = 1.0; ATOMIC w_imag = 0.0; const double theta = 2.0 * ((int) sign) * M_PI / ((double) (2 * dual)); const ATOMIC s = sin (theta); const ATOMIC t = sin (theta / 2.0); const ATOMIC s2 = 2.0 * t * t; size_t a, b; for (b = 0; b < dual; b++) { for (a = 0; a < n; a+= 2 * dual) { const size_t i = b + a; const size_t j = b + a + dual; const ATOMIC t1_real = REAL(data,stride,i) + REAL(data,stride,j); const ATOMIC t1_imag = IMAG(data,stride,i) + IMAG(data,stride,j); const ATOMIC t2_real = REAL(data,stride,i) - REAL(data,stride,j); const ATOMIC t2_imag = IMAG(data,stride,i) - IMAG(data,stride,j); REAL(data,stride,i) = t1_real; IMAG(data,stride,i) = t1_imag; REAL(data,stride,j) = w_real*t2_real - w_imag * t2_imag; IMAG(data,stride,j) = w_real*t2_imag + w_imag * t2_real; } /* trignometric recurrence for w-> exp(i theta) w */ { const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real; const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag; w_real = tmp_real; w_imag = tmp_imag; } } dual /= 2; } /* bit reverse the ordering of output data for decimation in frequency algorithm */ status = FUNCTION(fft_complex,bitreverse_order)(data, stride, n, logn) ; return status; } drc-3.2.2/source/gsl/gsl_machine.h0000644000076400001450000000733512616157443016001 0ustar denisitadm/* Author: B. Gough and G. Jungman */ #ifndef __GSL_MACHINE_H__ #define __GSL_MACHINE_H__ #include #include /* magic constants; mostly for the benefit of the implementation */ /* -*-MACHINE CONSTANTS-*- * * PLATFORM: Whiz-O-Matic 9000 * FP_PLATFORM: IEEE-Virtual * HOSTNAME: nnn.lanl.gov * DATE: Fri Nov 20 17:53:26 MST 1998 */ #define GSL_DBL_EPSILON 2.2204460492503131e-16 #define GSL_SQRT_DBL_EPSILON 1.4901161193847656e-08 #define GSL_ROOT3_DBL_EPSILON 6.0554544523933429e-06 #define GSL_ROOT4_DBL_EPSILON 1.2207031250000000e-04 #define GSL_ROOT5_DBL_EPSILON 7.4009597974140505e-04 #define GSL_ROOT6_DBL_EPSILON 2.4607833005759251e-03 #define GSL_LOG_DBL_EPSILON (-3.6043653389117154e+01) #define GSL_DBL_MIN 2.2250738585072014e-308 #define GSL_SQRT_DBL_MIN 1.4916681462400413e-154 #define GSL_ROOT3_DBL_MIN 2.8126442852362996e-103 #define GSL_ROOT4_DBL_MIN 1.2213386697554620e-77 #define GSL_ROOT5_DBL_MIN 2.9476022969691763e-62 #define GSL_ROOT6_DBL_MIN 5.3034368905798218e-52 #define GSL_LOG_DBL_MIN (-7.0839641853226408e+02) #define GSL_DBL_MAX 1.7976931348623157e+308 #define GSL_SQRT_DBL_MAX 1.3407807929942596e+154 #define GSL_ROOT3_DBL_MAX 5.6438030941222897e+102 #define GSL_ROOT4_DBL_MAX 1.1579208923731620e+77 #define GSL_ROOT5_DBL_MAX 4.4765466227572707e+61 #define GSL_ROOT6_DBL_MAX 2.3756689782295612e+51 #define GSL_LOG_DBL_MAX 7.0978271289338397e+02 #define GSL_FLT_EPSILON 1.1920928955078125e-07 #define GSL_SQRT_FLT_EPSILON 3.4526698300124393e-04 #define GSL_ROOT3_FLT_EPSILON 4.9215666011518501e-03 #define GSL_ROOT4_FLT_EPSILON 1.8581361171917516e-02 #define GSL_ROOT5_FLT_EPSILON 4.1234622211652937e-02 #define GSL_ROOT6_FLT_EPSILON 7.0153878019335827e-02 #define GSL_LOG_FLT_EPSILON (-1.5942385152878742e+01) #define GSL_FLT_MIN 1.1754943508222875e-38 #define GSL_SQRT_FLT_MIN 1.0842021724855044e-19 #define GSL_ROOT3_FLT_MIN 2.2737367544323241e-13 #define GSL_ROOT4_FLT_MIN 3.2927225399135965e-10 #define GSL_ROOT5_FLT_MIN 2.5944428542140822e-08 #define GSL_ROOT6_FLT_MIN 4.7683715820312542e-07 #define GSL_LOG_FLT_MIN (-8.7336544750553102e+01) #define GSL_FLT_MAX 3.4028234663852886e+38 #define GSL_SQRT_FLT_MAX 1.8446743523953730e+19 #define GSL_ROOT3_FLT_MAX 6.9814635196223242e+12 #define GSL_ROOT4_FLT_MAX 4.2949672319999986e+09 #define GSL_ROOT5_FLT_MAX 5.0859007855960041e+07 #define GSL_ROOT6_FLT_MAX 2.6422459233807749e+06 #define GSL_LOG_FLT_MAX 8.8722839052068352e+01 #define GSL_SFLT_EPSILON 4.8828125000000000e-04 #define GSL_SQRT_SFLT_EPSILON 2.2097086912079612e-02 #define GSL_ROOT3_SFLT_EPSILON 7.8745065618429588e-02 #define GSL_ROOT4_SFLT_EPSILON 1.4865088937534013e-01 #define GSL_ROOT5_SFLT_EPSILON 2.1763764082403100e-01 #define GSL_ROOT6_SFLT_EPSILON 2.8061551207734325e-01 #define GSL_LOG_SFLT_EPSILON (-7.6246189861593985e+00) /* !MACHINE CONSTANTS! */ /* a little internal backwards compatibility */ #define GSL_MACH_EPS GSL_DBL_EPSILON /* Here are the constants related to or derived from * machine constants. These are not to be confused with * the constants that define various precision levels * for the precision/error system. * * This information is determined at configure time * and is platform dependent. Edit at your own risk. * * PLATFORM: WHIZ-O-MATIC * CONFIG-DATE: Thu Nov 19 19:27:18 MST 1998 * CONFIG-HOST: nnn.lanl.gov */ /* machine precision constants */ /* #define GSL_MACH_EPS 1.0e-15 */ #define GSL_SQRT_MACH_EPS 3.2e-08 #define GSL_ROOT3_MACH_EPS 1.0e-05 #define GSL_ROOT4_MACH_EPS 0.000178 #define GSL_ROOT5_MACH_EPS 0.00100 #define GSL_ROOT6_MACH_EPS 0.00316 #define GSL_LOG_MACH_EPS (-34.54) #endif /* __GSL_MACHINE_H__ */ drc-3.2.2/source/gsl/gsl_fft_complex_float.h0000644000076400001450000001234512616157443020065 0ustar denisitadm/* fft/gsl_fft_complex_float.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_FFT_COMPLEX_FLOAT_H__ #define __GSL_FFT_COMPLEX_FLOAT_H__ #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS /* Power of 2 routines */ int gsl_fft_complex_float_radix2_forward (gsl_complex_packed_array_float data, const size_t stride, const size_t n); int gsl_fft_complex_float_radix2_backward (gsl_complex_packed_array_float data, const size_t stride, const size_t n); int gsl_fft_complex_float_radix2_inverse (gsl_complex_packed_array_float data, const size_t stride, const size_t n); int gsl_fft_complex_float_radix2_transform (gsl_complex_packed_array_float data, const size_t stride, const size_t n, const gsl_fft_direction sign); int gsl_fft_complex_float_radix2_dif_forward (gsl_complex_packed_array_float data, const size_t stride, const size_t n); int gsl_fft_complex_float_radix2_dif_backward (gsl_complex_packed_array_float data, const size_t stride, const size_t n); int gsl_fft_complex_float_radix2_dif_inverse (gsl_complex_packed_array_float data, const size_t stride, const size_t n); int gsl_fft_complex_float_radix2_dif_transform (gsl_complex_packed_array_float data, const size_t stride, const size_t n, const gsl_fft_direction sign); /* Mixed Radix general-N routines */ typedef struct { size_t n; size_t nf; size_t factor[64]; gsl_complex_float *twiddle[64]; gsl_complex_float *trig; } gsl_fft_complex_wavetable_float; typedef struct { size_t n; float *scratch; } gsl_fft_complex_workspace_float; gsl_fft_complex_wavetable_float *gsl_fft_complex_wavetable_float_alloc (size_t n); void gsl_fft_complex_wavetable_float_free (gsl_fft_complex_wavetable_float * wavetable); gsl_fft_complex_workspace_float *gsl_fft_complex_workspace_float_alloc (size_t n); void gsl_fft_complex_workspace_float_free (gsl_fft_complex_workspace_float * workspace); int gsl_fft_complex_float_memcpy (gsl_fft_complex_wavetable_float * dest, gsl_fft_complex_wavetable_float * src); int gsl_fft_complex_float_forward (gsl_complex_packed_array_float data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable_float * wavetable, gsl_fft_complex_workspace_float * work); int gsl_fft_complex_float_backward (gsl_complex_packed_array_float data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable_float * wavetable, gsl_fft_complex_workspace_float * work); int gsl_fft_complex_float_inverse (gsl_complex_packed_array_float data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable_float * wavetable, gsl_fft_complex_workspace_float * work); int gsl_fft_complex_float_transform (gsl_complex_packed_array_float data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable_float * wavetable, gsl_fft_complex_workspace_float * work, const gsl_fft_direction sign); __END_DECLS #endif /* __GSL_FFT_COMPLEX_FLOAT_H__ */ drc-3.2.2/source/gsl/hc_unpack.c0000644000076400001450000000547612616157443015462 0ustar denisitadm/* fft/hc_unpack.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ int FUNCTION(gsl_fft_halfcomplex,unpack) (const BASE halfcomplex_coefficient[], BASE complex_coefficient[], const size_t stride, const size_t n) { size_t i; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } REAL(complex_coefficient,stride,0) = halfcomplex_coefficient[0]; IMAG(complex_coefficient,stride,0) = 0.0; for (i = 1; i < n - i; i++) { const ATOMIC hc_real = halfcomplex_coefficient[(2 * i - 1) * stride]; const ATOMIC hc_imag = halfcomplex_coefficient[2 * i * stride]; REAL(complex_coefficient,stride,i) = hc_real; IMAG(complex_coefficient,stride,i) = hc_imag; REAL(complex_coefficient,stride,n - i) = hc_real; IMAG(complex_coefficient,stride,n - i) = -hc_imag; } if (i == n - i) { REAL(complex_coefficient,stride,i) = halfcomplex_coefficient[(n - 1) * stride]; IMAG(complex_coefficient,stride,i) = 0.0; } return 0; } int FUNCTION(gsl_fft_halfcomplex,radix2_unpack) (const BASE halfcomplex_coefficient[], BASE complex_coefficient[], const size_t stride, const size_t n) { size_t i; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } REAL(complex_coefficient,stride,0) = halfcomplex_coefficient[0]; IMAG(complex_coefficient,stride,0) = 0.0; for (i = 1; i < n - i; i++) { const ATOMIC hc_real = halfcomplex_coefficient[i * stride]; const ATOMIC hc_imag = halfcomplex_coefficient[(n - i) * stride]; REAL(complex_coefficient,stride,i) = hc_real; IMAG(complex_coefficient,stride,i) = hc_imag; REAL(complex_coefficient,stride,n - i) = hc_real; IMAG(complex_coefficient,stride,n - i) = -hc_imag; } if (i == n - i) { REAL(complex_coefficient,stride,i) = halfcomplex_coefficient[i * stride]; IMAG(complex_coefficient,stride,i) = 0.0; } return 0; } drc-3.2.2/source/gsl/real_pass_5.c0000644000076400001450000002437212616157443015720 0ustar denisitadm/* fft/real_pass_5.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_real,pass_5) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[]) { size_t k, k1; const size_t factor = 5; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; const ATOMIC sina = sin (2.0 * M_PI / 5.0); const ATOMIC sinb = sin (2.0 * M_PI / 10.0); for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const size_t from3 = from2 + m; const size_t from4 = from3 + m; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC z3_real = VECTOR(in,istride,from3); const ATOMIC z4_real = VECTOR(in,istride,from4); /* t1 = z1 + z4 */ const ATOMIC t1_real = z1_real + z4_real; /* t2 = z2 + z3 */ const ATOMIC t2_real = z2_real + z3_real; /* t3 = z1 - z4 */ const ATOMIC t3_real = z1_real - z4_real; /* t4 = z2 - z3 */ const ATOMIC t4_real = z2_real - z3_real; /* t5 = t1 + t2 */ const ATOMIC t5_real = t1_real + t2_real; /* t6 = (sqrt(5)/4)(t1 - t2) */ const ATOMIC t6_real = (sqrt (5.0) / 4.0) * (t1_real - t2_real); /* t7 = z0 - ((t5)/4) */ const ATOMIC t7_real = z0_real - t5_real / 4.0; /* t8 = t7 + t6 */ const ATOMIC t8_real = t7_real + t6_real; /* t9 = t7 - t6 */ const ATOMIC t9_real = t7_real - t6_real; /* t10 = -(sin(2 pi/5) t3 + sin(2 pi/10) t4 ) */ const ATOMIC t10_real = -sina * t3_real - sinb * t4_real; /* t11 = -(sin(2 pi/10) t3 - sin(2 pi/5) t4) */ const ATOMIC t11_real = -sinb * t3_real + sina * t4_real; /* x0 = z0 + t5 */ const ATOMIC x0_real = z0_real + t5_real; /* x1 = t8 + i t10 */ const ATOMIC x1_real = t8_real; const ATOMIC x1_imag = t10_real; /* x2 = t9 + i t11 */ const ATOMIC x2_real = t9_real; const ATOMIC x2_imag = t11_real; const size_t to0 = product * k1; const size_t to1 = to0 + 2 * product_1 - 1; const size_t to2 = to1 + 2 * product_1; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to1 + 1) = x1_imag; VECTOR(out,ostride,to2) = x2_real; VECTOR(out,ostride,to2 + 1) = x2_imag; } if (product_1 == 1) return; for (k = 1; k < (product_1 + 1) / 2; k++) { const ATOMIC w1_real = GSL_REAL(twiddle1[k - 1]); const ATOMIC w1_imag = -GSL_IMAG(twiddle1[k - 1]); const ATOMIC w2_real = GSL_REAL(twiddle2[k - 1]); const ATOMIC w2_imag = -GSL_IMAG(twiddle2[k - 1]); const ATOMIC w3_real = GSL_REAL(twiddle3[k - 1]); const ATOMIC w3_imag = -GSL_IMAG(twiddle3[k - 1]); const ATOMIC w4_real = GSL_REAL(twiddle4[k - 1]); const ATOMIC w4_imag = -GSL_IMAG(twiddle4[k - 1]); for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + 2 * k - 1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const size_t from3 = from2 + m; const size_t from4 = from3 + m; const ATOMIC f0_real = VECTOR(in,istride,from0); const ATOMIC f0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC f1_real = VECTOR(in,istride,from1); const ATOMIC f1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC f2_real = VECTOR(in,istride,from2); const ATOMIC f2_imag = VECTOR(in,istride,from2 + 1); const ATOMIC f3_real = VECTOR(in,istride,from3); const ATOMIC f3_imag = VECTOR(in,istride,from3 + 1); const ATOMIC f4_real = VECTOR(in,istride,from4); const ATOMIC f4_imag = VECTOR(in,istride,from4 + 1); const ATOMIC z0_real = f0_real; const ATOMIC z0_imag = f0_imag; const ATOMIC z1_real = w1_real * f1_real - w1_imag * f1_imag; const ATOMIC z1_imag = w1_real * f1_imag + w1_imag * f1_real; const ATOMIC z2_real = w2_real * f2_real - w2_imag * f2_imag; const ATOMIC z2_imag = w2_real * f2_imag + w2_imag * f2_real; const ATOMIC z3_real = w3_real * f3_real - w3_imag * f3_imag; const ATOMIC z3_imag = w3_real * f3_imag + w3_imag * f3_real; const ATOMIC z4_real = w4_real * f4_real - w4_imag * f4_imag; const ATOMIC z4_imag = w4_real * f4_imag + w4_imag * f4_real; /* compute x = W(5) z */ /* t1 = z1 + z4 */ const ATOMIC t1_real = z1_real + z4_real; const ATOMIC t1_imag = z1_imag + z4_imag; /* t2 = z2 + z3 */ const ATOMIC t2_real = z2_real + z3_real; const ATOMIC t2_imag = z2_imag + z3_imag; /* t3 = z1 - z4 */ const ATOMIC t3_real = z1_real - z4_real; const ATOMIC t3_imag = z1_imag - z4_imag; /* t4 = z2 - z3 */ const ATOMIC t4_real = z2_real - z3_real; const ATOMIC t4_imag = z2_imag - z3_imag; /* t5 = t1 + t2 */ const ATOMIC t5_real = t1_real + t2_real; const ATOMIC t5_imag = t1_imag + t2_imag; /* t6 = (sqrt(5)/4)(t1 - t2) */ const ATOMIC t6_real = (sqrt (5.0) / 4.0) * (t1_real - t2_real); const ATOMIC t6_imag = (sqrt (5.0) / 4.0) * (t1_imag - t2_imag); /* t7 = z0 - ((t5)/4) */ const ATOMIC t7_real = z0_real - t5_real / 4.0; const ATOMIC t7_imag = z0_imag - t5_imag / 4.0; /* t8 = t7 + t6 */ const ATOMIC t8_real = t7_real + t6_real; const ATOMIC t8_imag = t7_imag + t6_imag; /* t9 = t7 - t6 */ const ATOMIC t9_real = t7_real - t6_real; const ATOMIC t9_imag = t7_imag - t6_imag; /* t10 = - (sin(2 pi/5) t3 + sin(2 pi/10) t4) */ const ATOMIC t10_real = -sina * t3_real - sinb * t4_real; const ATOMIC t10_imag = -sina * t3_imag - sinb * t4_imag; /* t11 = -(sin(2 pi/10) t3 - sin(2 pi/5) t4) */ const ATOMIC t11_real = -sinb * t3_real + sina * t4_real; const ATOMIC t11_imag = -sinb * t3_imag + sina * t4_imag; /* x0 = z0 + t5 */ const ATOMIC x0_real = z0_real + t5_real; const ATOMIC x0_imag = z0_imag + t5_imag; /* x1 = t8 + i t10 */ const ATOMIC x1_real = t8_real - t10_imag; const ATOMIC x1_imag = t8_imag + t10_real; /* x2 = t9 + i t11 */ const ATOMIC x2_real = t9_real - t11_imag; const ATOMIC x2_imag = t9_imag + t11_real; /* x3 = t9 - i t11 */ const ATOMIC x3_real = t9_real + t11_imag; const ATOMIC x3_imag = t9_imag - t11_real; /* x4 = t8 - i t10 */ const ATOMIC x4_real = t8_real + t10_imag; const ATOMIC x4_imag = t8_imag - t10_real; const size_t to0 = k1 * product + 2 * k - 1; const size_t to1 = to0 + 2 * product_1; const size_t to2 = to1 + 2 * product_1; const size_t to3 = 2 * product_1 - 2 * k + k1 * product - 1; const size_t to4 = to3 + 2 * product_1; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to1 + 1) = x1_imag; VECTOR(out,ostride,to2) = x2_real; VECTOR(out,ostride,to2 + 1) = x2_imag; VECTOR(out,ostride,to3) = x4_real; VECTOR(out,ostride,to3 + 1) = -x4_imag; VECTOR(out,ostride,to4) = x3_real; VECTOR(out,ostride,to4 + 1) = -x3_imag; } } if (product_1 % 2 == 1) return; for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + product_1 - 1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const size_t from3 = from2 + m; const size_t from4 = from3 + m; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC z3_real = VECTOR(in,istride,from3); const ATOMIC z4_real = VECTOR(in,istride,from4); const ATOMIC t1 = z1_real - z4_real; const ATOMIC t2 = z1_real + z4_real; const ATOMIC t3 = z2_real - z3_real; const ATOMIC t4 = z2_real + z3_real; const ATOMIC t5 = t1 - t3; const ATOMIC t6 = z0_real + t5 / 4.0; const ATOMIC t7 = (sqrt (5.0) / 4.0) * (t1 + t3); const size_t to0 = k1 * product + product_1 - 1; const size_t to1 = to0 + 2 * product_1; const size_t to2 = to1 + 2 * product_1; VECTOR(out,ostride,to0) = t6 + t7; VECTOR(out,ostride,to0 + 1) = -sinb * t2 - sina * t4; VECTOR(out,ostride,to1) = t6 - t7; VECTOR(out,ostride,to1 + 1) = -sina * t2 + sinb * t4; VECTOR(out,ostride,to2) = z0_real - t5; } return; } drc-3.2.2/source/gsl/signals.h0000644000076400001450000000565012616157443015166 0ustar denisitadm/* fft/signals.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ int FUNCTION(fft_signal,complex_pulse) (const size_t k, const size_t n, const size_t stride, const BASE z_real, const BASE z_imag, BASE data[], BASE fft[]); int FUNCTION(fft_signal,complex_constant) (const size_t n, const size_t stride, const BASE z_real, const BASE z_imag, BASE data[], BASE fft[]); int FUNCTION(fft_signal,complex_exp) (const int k, const size_t n, const size_t stride, const BASE z_real, const BASE z_imag, BASE data[], BASE fft[]); int FUNCTION(fft_signal,complex_exppair) (const int k1, const int k2, const size_t n, const size_t stride, const BASE z1_real, const BASE z1_imag, const BASE z2_real, const BASE z2_imag, BASE data[], BASE fft[]); int FUNCTION(fft_signal,complex_noise) (const size_t n, const size_t stride, BASE data[], BASE fft[]); int FUNCTION(fft_signal,real_noise) (const size_t n, const size_t stride, BASE data[], BASE fft[]); drc-3.2.2/source/gsl/gsl_precision.h0000644000076400001450000000336412616157443016366 0ustar denisitadm/* gsl_precision.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Author: B. Gough and G. Jungman */ #ifndef __GSL_PRECISION_H__ #define __GSL_PRECISION_H__ #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS /* A type for the precision indicator. * This is mainly for pedagogy. */ typedef unsigned int gsl_prec_t; /* The number of precision types. * Remember that precision-mode * can index an array. */ #define _GSL_PREC_T_NUM 3 /* Arrays containing derived * precision constants for the * different precision levels. */ GSL_VAR const double gsl_prec_eps[]; GSL_VAR const double gsl_prec_sqrt_eps[]; GSL_VAR const double gsl_prec_root3_eps[]; GSL_VAR const double gsl_prec_root4_eps[]; GSL_VAR const double gsl_prec_root5_eps[]; GSL_VAR const double gsl_prec_root6_eps[]; __END_DECLS #endif /* __GSL_PRECISION_H__ */ drc-3.2.2/source/gsl/real_pass.h0000644000076400001450000000655312616157443015502 0ustar denisitadm/* fft/real_pass.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_real,pass_2) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]); static void FUNCTION(fft_real,pass_3) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[]); static void FUNCTION(fft_real,pass_4) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[]); static void FUNCTION(fft_real,pass_5) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[]); static void FUNCTION(fft_real,pass_n) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t factor, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]); drc-3.2.2/source/gsl/c_pass_5.c0000644000076400001450000001703512616157443015215 0ustar denisitadm/* fft/c_pass_5.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_5) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[]) { size_t i = 0, j = 0; size_t k, k1; const size_t factor = 5; const size_t m = n / factor; const size_t q = n / product; const size_t p_1 = product / factor; const size_t jump = (factor - 1) * p_1; const ATOMIC sin_2pi_by_5 = sin (2.0 * M_PI / 5.0); const ATOMIC sin_2pi_by_10 = sin (2.0 * M_PI / 10.0); for (k = 0; k < q; k++) { ATOMIC w1_real, w1_imag, w2_real, w2_imag, w3_real, w3_imag, w4_real, w4_imag; if (k == 0) { w1_real = 1.0; w1_imag = 0.0; w2_real = 1.0; w2_imag = 0.0; w3_real = 1.0; w3_imag = 0.0; w4_real = 1.0; w4_imag = 0.0; } else { if (sign == gsl_fft_forward) { /* forward tranform */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = GSL_IMAG(twiddle3[k - 1]); w4_real = GSL_REAL(twiddle4[k - 1]); w4_imag = GSL_IMAG(twiddle4[k - 1]); } else { /* backward tranform: w -> conjugate(w) */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = -GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = -GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = -GSL_IMAG(twiddle3[k - 1]); w4_real = GSL_REAL(twiddle4[k - 1]); w4_imag = -GSL_IMAG(twiddle4[k - 1]); } } for (k1 = 0; k1 < p_1; k1++) { ATOMIC x0_real, x0_imag, x1_real, x1_imag, x2_real, x2_imag, x3_real, x3_imag, x4_real, x4_imag; const ATOMIC z0_real = REAL(in,istride,i); const ATOMIC z0_imag = IMAG(in,istride,i); const ATOMIC z1_real = REAL(in,istride,i + m); const ATOMIC z1_imag = IMAG(in,istride,i + m); const ATOMIC z2_real = REAL(in,istride,i + 2*m); const ATOMIC z2_imag = IMAG(in,istride,i + 2*m); const ATOMIC z3_real = REAL(in,istride,i + 3*m); const ATOMIC z3_imag = IMAG(in,istride,i + 3*m); const ATOMIC z4_real = REAL(in,istride,i + 4*m); const ATOMIC z4_imag = IMAG(in,istride,i + 4*m); /* compute x = W(5) z */ /* t1 = z1 + z4 */ const ATOMIC t1_real = z1_real + z4_real; const ATOMIC t1_imag = z1_imag + z4_imag; /* t2 = z2 + z3 */ const ATOMIC t2_real = z2_real + z3_real; const ATOMIC t2_imag = z2_imag + z3_imag; /* t3 = z1 - z4 */ const ATOMIC t3_real = z1_real - z4_real; const ATOMIC t3_imag = z1_imag - z4_imag; /* t4 = z2 - z3 */ const ATOMIC t4_real = z2_real - z3_real; const ATOMIC t4_imag = z2_imag - z3_imag; /* t5 = t1 + t2 */ const ATOMIC t5_real = t1_real + t2_real; const ATOMIC t5_imag = t1_imag + t2_imag; /* t6 = (sqrt(5)/4)(t1 - t2) */ const ATOMIC t6_real = (sqrt (5.0) / 4.0) * (t1_real - t2_real); const ATOMIC t6_imag = (sqrt (5.0) / 4.0) * (t1_imag - t2_imag); /* t7 = z0 - ((t5)/4) */ const ATOMIC t7_real = z0_real - t5_real / 4.0; const ATOMIC t7_imag = z0_imag - t5_imag / 4.0; /* t8 = t7 + t6 */ const ATOMIC t8_real = t7_real + t6_real; const ATOMIC t8_imag = t7_imag + t6_imag; /* t9 = t7 - t6 */ const ATOMIC t9_real = t7_real - t6_real; const ATOMIC t9_imag = t7_imag - t6_imag; /* t10 = sin(2 pi/5) t3 + sin(2 pi/10) t4 */ const ATOMIC t10_real = ((int) sign) * (sin_2pi_by_5 * t3_real + sin_2pi_by_10 * t4_real); const ATOMIC t10_imag = ((int) sign) * (sin_2pi_by_5 * t3_imag + sin_2pi_by_10 * t4_imag); /* t11 = sin(2 pi/10) t3 - sin(2 pi/5) t4 */ const ATOMIC t11_real = ((int) sign) * (sin_2pi_by_10 * t3_real - sin_2pi_by_5 * t4_real); const ATOMIC t11_imag = ((int) sign) * (sin_2pi_by_10 * t3_imag - sin_2pi_by_5 * t4_imag); /* x0 = z0 + t5 */ x0_real = z0_real + t5_real; x0_imag = z0_imag + t5_imag; /* x1 = t8 + i t10 */ x1_real = t8_real - t10_imag; x1_imag = t8_imag + t10_real; /* x2 = t9 + i t11 */ x2_real = t9_real - t11_imag; x2_imag = t9_imag + t11_real; /* x3 = t9 - i t11 */ x3_real = t9_real + t11_imag; x3_imag = t9_imag - t11_real; /* x4 = t8 - i t10 */ x4_real = t8_real + t10_imag; x4_imag = t8_imag - t10_real; /* apply twiddle factors */ /* to0 = 1 * x0 */ REAL(out,ostride,j) = x0_real; IMAG(out,ostride,j) = x0_imag; /* to1 = w1 * x1 */ REAL(out,ostride,j + p_1) = w1_real * x1_real - w1_imag * x1_imag; IMAG(out,ostride,j + p_1) = w1_real * x1_imag + w1_imag * x1_real; /* to2 = w2 * x2 */ REAL(out,ostride,j + 2*p_1) = w2_real * x2_real - w2_imag * x2_imag; IMAG(out,ostride,j+2*p_1) = w2_real * x2_imag + w2_imag * x2_real; /* to3 = w3 * x3 */ REAL(out,ostride,j+3*p_1) = w3_real * x3_real - w3_imag * x3_imag; IMAG(out,ostride,j+3*p_1) = w3_real * x3_imag + w3_imag * x3_real; /* to4 = w4 * x4 */ REAL(out,ostride,j+4*p_1) = w4_real * x4_real - w4_imag * x4_imag; IMAG(out,ostride,j+4*p_1) = w4_real * x4_imag + w4_imag * x4_real; i++; j++; } j += jump; } return 0; } drc-3.2.2/source/gsl/signals_source.c0000644000076400001450000001613712616157443016543 0ustar denisitadm/* fft/signals_source.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "signals.h" int FUNCTION(fft_signal,complex_pulse) (const size_t k, const size_t n, const size_t stride, const BASE z_real, const BASE z_imag, BASE data[], BASE fft[]) { size_t j; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } /* gsl_complex pulse at position k, data[j] = z * delta_{jk} */ for (j = 0; j < n; j++) { REAL(data,stride,j) = 0.0; IMAG(data,stride,j) = 0.0; } REAL(data,stride,k % n) = z_real; IMAG(data,stride,k % n) = z_imag; /* fourier transform, fft[j] = z * exp(-2 pi i j k / n) */ for (j = 0; j < n; j++) { const double arg = -2 * M_PI * ((double) ((j * k) % n)) / ((double) n); const BASE w_real = (BASE)cos (arg); const BASE w_imag = (BASE)sin (arg); REAL(fft,stride,j) = w_real * z_real - w_imag * z_imag; IMAG(fft,stride,j) = w_real * z_imag + w_imag * z_real; } return 0; } int FUNCTION(fft_signal,complex_constant) (const size_t n, const size_t stride, const BASE z_real, const BASE z_imag, BASE data[], BASE fft[]) { size_t j; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } /* constant, data[j] = z */ for (j = 0; j < n; j++) { REAL(data,stride,j) = z_real; IMAG(data,stride,j) = z_imag; } /* fourier transform, fft[j] = n z delta_{j0} */ for (j = 0; j < n; j++) { REAL(fft,stride,j) = 0.0; IMAG(fft,stride,j) = 0.0; } REAL(fft,stride,0) = ((BASE) n) * z_real; IMAG(fft,stride,0) = ((BASE) n) * z_imag; return 0; } int FUNCTION(fft_signal,complex_exp) (const int k, const size_t n, const size_t stride, const BASE z_real, const BASE z_imag, BASE data[], BASE fft[]) { size_t j; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } /* exponential, data[j] = z * exp(2 pi i j k) */ for (j = 0; j < n; j++) { const double arg = 2 * M_PI * ((double) ((j * k) % n)) / ((double) n); const BASE w_real = (BASE)cos (arg); const BASE w_imag = (BASE)sin (arg); REAL(data,stride,j) = w_real * z_real - w_imag * z_imag; IMAG(data,stride,j) = w_real * z_imag + w_imag * z_real; } /* fourier transform, fft[j] = z * delta{(j - k),0} */ for (j = 0; j < n; j++) { REAL(fft,stride,j) = 0.0; IMAG(fft,stride,j) = 0.0; } { int freq; if (k <= 0) { freq = (n-k) % n ; } else { freq = (k % n); }; REAL(fft,stride,freq) = ((BASE) n) * z_real; IMAG(fft,stride,freq) = ((BASE) n) * z_imag; } return 0; } int FUNCTION(fft_signal,complex_exppair) (const int k1, const int k2, const size_t n, const size_t stride, const BASE z1_real, const BASE z1_imag, const BASE z2_real, const BASE z2_imag, BASE data[], BASE fft[]) { size_t j; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } /* exponential, data[j] = z1 * exp(2 pi i j k1) + z2 * exp(2 pi i j k2) */ for (j = 0; j < n; j++) { const double arg1 = 2 * M_PI * ((double) ((j * k1) % n)) / ((double) n); const BASE w1_real = (BASE)cos (arg1); const BASE w1_imag = (BASE)sin (arg1); const double arg2 = 2 * M_PI * ((double) ((j * k2) % n)) / ((double) n); const BASE w2_real = (BASE)cos (arg2); const BASE w2_imag = (BASE)sin (arg2); REAL(data,stride,j) = w1_real * z1_real - w1_imag * z1_imag; IMAG(data,stride,j) = w1_real * z1_imag + w1_imag * z1_real; REAL(data,stride,j) += w2_real * z2_real - w2_imag * z2_imag; IMAG(data,stride,j) += w2_real * z2_imag + w2_imag * z2_real; } /* fourier transform, fft[j] = z1 * delta{(j - k1),0} + z2 * delta{(j - k2,0)} */ for (j = 0; j < n; j++) { REAL(fft,stride,j) = 0.0; IMAG(fft,stride,j) = 0.0; } { int freq1, freq2; if (k1 <= 0) { freq1 = (n - k1) % n; } else { freq1 = (k1 % n); }; if (k2 <= 0) { freq2 = (n - k2) % n; } else { freq2 = (k2 % n); }; REAL(fft,stride,freq1) += ((BASE) n) * z1_real; IMAG(fft,stride,freq1) += ((BASE) n) * z1_imag; REAL(fft,stride,freq2) += ((BASE) n) * z2_real; IMAG(fft,stride,freq2) += ((BASE) n) * z2_imag; } return 0; } int FUNCTION(fft_signal,complex_noise) (const size_t n, const size_t stride, BASE data[], BASE fft[]) { size_t i; int status; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } for (i = 0; i < n; i++) { REAL(data,stride,i) = (BASE)urand(); IMAG(data,stride,i) = (BASE)urand(); } /* compute the dft */ status = FUNCTION(gsl_dft_complex,forward) (data, stride, n, fft); return status; } int FUNCTION(fft_signal,real_noise) (const size_t n, const size_t stride, BASE data[], BASE fft[]) { size_t i; int status; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } for (i = 0; i < n; i++) { REAL(data,stride,i) = (BASE)urand(); IMAG(data,stride,i) = 0.0; } /* compute the dft */ status = FUNCTION(gsl_dft_complex,forward) (data, stride, n, fft); return status; } drc-3.2.2/source/gsl/gsl_message.h0000644000076400001450000000456412616157443016022 0ustar denisitadm/* err/gsl_message.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_MESSAGE_H__ #define __GSL_MESSAGE_H__ #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS /* Provide a general messaging service for client use. Messages can * be selectively turned off at compile time by defining an * appropriate message mask. Client code which uses the GSL_MESSAGE() * macro must provide a mask which is or'ed with the GSL_MESSAGE_MASK. * * The messaging service can be completely turned off * by defining GSL_MESSAGING_OFF. */ void gsl_message(const char * message, const char * file, int line, unsigned int mask); #ifndef GSL_MESSAGE_MASK #define GSL_MESSAGE_MASK 0xffffffffu /* default all messages allowed */ #endif GSL_VAR unsigned int gsl_message_mask ; /* Provide some symolic masks for client ease of use. */ enum { GSL_MESSAGE_MASK_A = 1, GSL_MESSAGE_MASK_B = 2, GSL_MESSAGE_MASK_C = 4, GSL_MESSAGE_MASK_D = 8, GSL_MESSAGE_MASK_E = 16, GSL_MESSAGE_MASK_F = 32, GSL_MESSAGE_MASK_G = 64, GSL_MESSAGE_MASK_H = 128 } ; #ifdef GSL_MESSAGING_OFF /* throw away messages */ #define GSL_MESSAGE(message, mask) do { } while(0) #else /* output all messages */ #define GSL_MESSAGE(message, mask) \ do { \ if (mask & GSL_MESSAGE_MASK) \ gsl_message (message, __FILE__, __LINE__, mask) ; \ } while (0) #endif __END_DECLS #endif /* __GSL_MESSAGE_H__ */ drc-3.2.2/source/gsl/signals.c0000644000076400001450000000077312616157443015162 0ustar denisitadm#include #include #include #include #include #include #include #include #include "complex_internal.h" #include "urand.c" #define BASE_DOUBLE #include "templates_on.h" #include "signals_source.c" #include "templates_off.h" #undef BASE_DOUBLE #define BASE_FLOAT #include "templates_on.h" #include "signals_source.c" #include "templates_off.h" #undef BASE_FLOAT drc-3.2.2/source/gsl/c_pass.h0000644000076400001450000001137112616157443014773 0ustar denisitadm/* fft/c_pass.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_2) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]); static int FUNCTION(fft_complex,pass_3) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[]); static int FUNCTION(fft_complex,pass_4) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[]); static int FUNCTION(fft_complex,pass_5) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[]); static int FUNCTION(fft_complex,pass_6) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[], const TYPE(gsl_complex) twiddle5[]); static int FUNCTION(fft_complex,pass_7) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[], const TYPE(gsl_complex) twiddle5[], const TYPE(gsl_complex) twiddle6[]); static int FUNCTION(fft_complex,pass_n) (BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t factor, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]); drc-3.2.2/source/gsl/hc_pass_5.c0000644000076400001450000002265713164706053015367 0ustar denisitadm/* fft/hc_pass_5.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_halfcomplex,pass_5) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[]) { size_t k, k1; size_t factor, q, m, product_1; const ATOMIC sina = sin (2.0 * M_PI / 5.0); const ATOMIC sinb = sin (2.0 * M_PI / 10.0); factor = 5; m = n / factor; q = n / product; product_1 = product / factor; for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 5 * k1 * q; const size_t from1 = from0 + 2 * q - 1; const size_t from2 = from1 + 2 * q; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC z2_imag = VECTOR(in,istride,from2 + 1); const ATOMIC t1_real = 2 * (z1_real + z2_real); const ATOMIC t2_real = 2 * (sqrt (5.0) / 4.0) * (z1_real - z2_real); const ATOMIC t3_real = z0_real - t1_real / 4.0; const ATOMIC t4_real = t2_real + t3_real; const ATOMIC t5_real = -t2_real + t3_real; const ATOMIC t6_imag = 2 * (sina * z1_imag + sinb * z2_imag); const ATOMIC t7_imag = 2 * (sinb * z1_imag - sina * z2_imag); const ATOMIC x0_real = z0_real + t1_real; const ATOMIC x1_real = t4_real - t6_imag; const ATOMIC x2_real = t5_real - t7_imag; const ATOMIC x3_real = t5_real + t7_imag; const ATOMIC x4_real = t4_real + t6_imag; const size_t to0 = q * k1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; const size_t to3 = to2 + m; const size_t to4 = to3 + m; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to2) = x2_real; VECTOR(out,ostride,to3) = x3_real; VECTOR(out,ostride,to4) = x4_real; } if (q == 1) return; for (k = 1; k < (q + 1) / 2; k++) { const ATOMIC w1_real = GSL_REAL(twiddle1[k - 1]); const ATOMIC w1_imag = GSL_IMAG(twiddle1[k - 1]); const ATOMIC w2_real = GSL_REAL(twiddle2[k - 1]); const ATOMIC w2_imag = GSL_IMAG(twiddle2[k - 1]); const ATOMIC w3_real = GSL_REAL(twiddle3[k - 1]); const ATOMIC w3_imag = GSL_IMAG(twiddle3[k - 1]); const ATOMIC w4_real = GSL_REAL(twiddle4[k - 1]); const ATOMIC w4_imag = GSL_IMAG(twiddle4[k - 1]); for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 5 * k1 * q + 2 * k - 1; const size_t from1 = from0 + 2 * q; const size_t from2 = from1 + 2 * q; const size_t from3 = 5 * k1 * q - 2 * k + 2 * q - 1; const size_t from4 = from3 + 2 * q; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC z2_imag = VECTOR(in,istride,from2 + 1); const ATOMIC z3_real = VECTOR(in,istride,from4); const ATOMIC z3_imag = -VECTOR(in,istride,from4 + 1); const ATOMIC z4_real = VECTOR(in,istride,from3); const ATOMIC z4_imag = -VECTOR(in,istride,from3 + 1); /* compute x = W(5) z */ /* t1 = z1 + z4 */ const ATOMIC t1_real = z1_real + z4_real; const ATOMIC t1_imag = z1_imag + z4_imag; /* t2 = z2 + z3 */ const ATOMIC t2_real = z2_real + z3_real; const ATOMIC t2_imag = z2_imag + z3_imag; /* t3 = z1 - z4 */ const ATOMIC t3_real = z1_real - z4_real; const ATOMIC t3_imag = z1_imag - z4_imag; /* t4 = z2 - z3 */ const ATOMIC t4_real = z2_real - z3_real; const ATOMIC t4_imag = z2_imag - z3_imag; /* t5 = t1 + t2 */ const ATOMIC t5_real = t1_real + t2_real; const ATOMIC t5_imag = t1_imag + t2_imag; /* t6 = (sqrt(5)/4)(t1 - t2) */ const ATOMIC t6_real = (sqrt (5.0) / 4.0) * (t1_real - t2_real); const ATOMIC t6_imag = (sqrt (5.0) / 4.0) * (t1_imag - t2_imag); /* t7 = z0 - ((t5)/4) */ const ATOMIC t7_real = z0_real - t5_real / 4.0; const ATOMIC t7_imag = z0_imag - t5_imag / 4.0; /* t8 = t7 + t6 */ const ATOMIC t8_real = t7_real + t6_real; const ATOMIC t8_imag = t7_imag + t6_imag; /* t9 = t7 - t6 */ const ATOMIC t9_real = t7_real - t6_real; const ATOMIC t9_imag = t7_imag - t6_imag; /* t10 = sin(2 pi/5) t3 + sin(2 pi/10) t4 */ const ATOMIC t10_real = sina * t3_real + sinb * t4_real; const ATOMIC t10_imag = sina * t3_imag + sinb * t4_imag; /* t11 = sin(2 pi/10) t3 - sin(2 pi/5) t4 */ const ATOMIC t11_real = sinb * t3_real - sina * t4_real; const ATOMIC t11_imag = sinb * t3_imag - sina * t4_imag; /* x0 = z0 + t5 */ const ATOMIC x0_real = z0_real + t5_real; const ATOMIC x0_imag = z0_imag + t5_imag; /* x1 = t8 + i t10 */ const ATOMIC x1_real = t8_real - t10_imag; const ATOMIC x1_imag = t8_imag + t10_real; /* x2 = t9 + i t11 */ const ATOMIC x2_real = t9_real - t11_imag; const ATOMIC x2_imag = t9_imag + t11_real; /* x3 = t9 - i t11 */ const ATOMIC x3_real = t9_real + t11_imag; const ATOMIC x3_imag = t9_imag - t11_real; /* x4 = t8 - i t10 */ const ATOMIC x4_real = t8_real + t10_imag; const ATOMIC x4_imag = t8_imag - t10_real; const size_t to0 = k1 * q + 2 * k - 1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; const size_t to3 = to2 + m; const size_t to4 = to3 + m; /* apply twiddle factors */ /* to0 = 1 * x0 */ VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; /* to1 = w1 * x1 */ VECTOR(out,ostride,to1) = w1_real * x1_real - w1_imag * x1_imag; VECTOR(out,ostride,to1 + 1) = w1_real * x1_imag + w1_imag * x1_real; /* to2 = w2 * x2 */ VECTOR(out,ostride,to2) = w2_real * x2_real - w2_imag * x2_imag; VECTOR(out,ostride,to2 + 1) = w2_real * x2_imag + w2_imag * x2_real; /* to3 = w3 * x3 */ VECTOR(out,ostride,to3) = w3_real * x3_real - w3_imag * x3_imag; VECTOR(out,ostride,to3 + 1) = w3_real * x3_imag + w3_imag * x3_real; /* to4 = w4 * x4 */ VECTOR(out,ostride,to4) = w4_real * x4_real - w4_imag * x4_imag; VECTOR(out,ostride,to4 + 1) = w4_real * x4_imag + w4_imag * x4_real; } } if (q % 2 == 1) return; for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 5 * k1 * q + q - 1; const size_t from1 = from0 + 2 * q; const size_t from2 = from1 + 2 * q; const ATOMIC z0_real = 2 * VECTOR(in,istride,from0); const ATOMIC z0_imag = 2 * VECTOR(in,istride,from0 + 1); const ATOMIC z1_real = 2 * VECTOR(in,istride,from1); const ATOMIC z1_imag = 2 * VECTOR(in,istride,from1 + 1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC t1_real = z0_real + z1_real; const ATOMIC t2_real = (t1_real / 4.0) - z2_real; const ATOMIC t3_real = (sqrt (5.0) / 4.0) * (z0_real - z1_real); const ATOMIC t4_real = sinb * z0_imag + sina * z1_imag; const ATOMIC t5_real = sina * z0_imag - sinb * z1_imag; const ATOMIC t6_real = t3_real + t2_real; const ATOMIC t7_real = t3_real - t2_real; const ATOMIC x0_real = t1_real + z2_real; const ATOMIC x1_real = t6_real - t4_real; const ATOMIC x2_real = t7_real - t5_real; const ATOMIC x3_real = -t7_real - t5_real; const ATOMIC x4_real = -t6_real - t4_real; const size_t to0 = k1 * q + q - 1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; const size_t to3 = to2 + m; const size_t to4 = to3 + m; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to2) = x2_real; VECTOR(out,ostride,to3) = x3_real; VECTOR(out,ostride,to4) = x4_real; } return; } drc-3.2.2/source/gsl/gsl_fft_complex.h0000644000076400001450000001133612616157443016677 0ustar denisitadm/* fft/gsl_fft_complex.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_FFT_COMPLEX_H__ #define __GSL_FFT_COMPLEX_H__ #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS /* Power of 2 routines */ int gsl_fft_complex_radix2_forward (gsl_complex_packed_array data, const size_t stride, const size_t n); int gsl_fft_complex_radix2_backward (gsl_complex_packed_array data, const size_t stride, const size_t n); int gsl_fft_complex_radix2_inverse (gsl_complex_packed_array data, const size_t stride, const size_t n); int gsl_fft_complex_radix2_transform (gsl_complex_packed_array data, const size_t stride, const size_t n, const gsl_fft_direction sign); int gsl_fft_complex_radix2_dif_forward (gsl_complex_packed_array data, const size_t stride, const size_t n); int gsl_fft_complex_radix2_dif_backward (gsl_complex_packed_array data, const size_t stride, const size_t n); int gsl_fft_complex_radix2_dif_inverse (gsl_complex_packed_array data, const size_t stride, const size_t n); int gsl_fft_complex_radix2_dif_transform (gsl_complex_packed_array data, const size_t stride, const size_t n, const gsl_fft_direction sign); /* Mixed Radix general-N routines */ typedef struct { size_t n; size_t nf; size_t factor[64]; gsl_complex *twiddle[64]; gsl_complex *trig; } gsl_fft_complex_wavetable; typedef struct { size_t n; double *scratch; } gsl_fft_complex_workspace; gsl_fft_complex_wavetable *gsl_fft_complex_wavetable_alloc (size_t n); void gsl_fft_complex_wavetable_free (gsl_fft_complex_wavetable * wavetable); gsl_fft_complex_workspace *gsl_fft_complex_workspace_alloc (size_t n); void gsl_fft_complex_workspace_free (gsl_fft_complex_workspace * workspace); int gsl_fft_complex_memcpy (gsl_fft_complex_wavetable * dest, gsl_fft_complex_wavetable * src); int gsl_fft_complex_forward (gsl_complex_packed_array data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable * wavetable, gsl_fft_complex_workspace * work); int gsl_fft_complex_backward (gsl_complex_packed_array data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable * wavetable, gsl_fft_complex_workspace * work); int gsl_fft_complex_inverse (gsl_complex_packed_array data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable * wavetable, gsl_fft_complex_workspace * work); int gsl_fft_complex_transform (gsl_complex_packed_array data, const size_t stride, const size_t n, const gsl_fft_complex_wavetable * wavetable, gsl_fft_complex_workspace * work, const gsl_fft_direction sign); __END_DECLS #endif /* __GSL_FFT_COMPLEX_H__ */ drc-3.2.2/source/gsl/gsl_fft_real_float.h0000644000076400001450000000451612616157443017342 0ustar denisitadm/* fft/gsl_fft_real_float.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_FFT_REAL_FLOAT_H__ #define __GSL_FFT_REAL_FLOAT_H__ #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS int gsl_fft_real_float_radix2_transform (float data[], const size_t stride, const size_t n) ; typedef struct { size_t n; size_t nf; size_t factor[64]; gsl_complex_float *twiddle[64]; gsl_complex_float *trig; } gsl_fft_real_wavetable_float; typedef struct { size_t n; float *scratch; } gsl_fft_real_workspace_float; gsl_fft_real_wavetable_float * gsl_fft_real_wavetable_float_alloc (size_t n); void gsl_fft_real_wavetable_float_free (gsl_fft_real_wavetable_float * wavetable); gsl_fft_real_workspace_float * gsl_fft_real_workspace_float_alloc (size_t n); void gsl_fft_real_workspace_float_free (gsl_fft_real_workspace_float * workspace); int gsl_fft_real_float_transform (float data[], const size_t stride, const size_t n, const gsl_fft_real_wavetable_float * wavetable, gsl_fft_real_workspace_float * work); int gsl_fft_real_float_unpack (const float real_float_coefficient[], float complex_coefficient[], const size_t stride, const size_t n); __END_DECLS #endif /* __GSL_FFT_REAL_FLOAT_H__ */ drc-3.2.2/source/gsl/gsl_minmax.h0000644000076400001450000000511012616157443015653 0ustar denisitadm/* gsl_minmax.h * * Copyright (C) 2008 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_MINMAX_H__ #define __GSL_MINMAX_H__ #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS /* Define MAX and MIN macros/functions if they don't exist. */ /* plain old macros for general use */ #define GSL_MAX(a,b) ((a) > (b) ? (a) : (b)) #define GSL_MIN(a,b) ((a) < (b) ? (a) : (b)) /* function versions of the above, in case they are needed */ double gsl_max (double a, double b); double gsl_min (double a, double b); /* inline-friendly strongly typed versions */ #ifdef HAVE_INLINE INLINE_FUN int GSL_MAX_INT (int a, int b); INLINE_FUN int GSL_MIN_INT (int a, int b); INLINE_FUN double GSL_MAX_DBL (double a, double b); INLINE_FUN double GSL_MIN_DBL (double a, double b); INLINE_FUN long double GSL_MAX_LDBL (long double a, long double b); INLINE_FUN long double GSL_MIN_LDBL (long double a, long double b); INLINE_FUN int GSL_MAX_INT (int a, int b) { return GSL_MAX (a, b); } INLINE_FUN int GSL_MIN_INT (int a, int b) { return GSL_MIN (a, b); } INLINE_FUN double GSL_MAX_DBL (double a, double b) { return GSL_MAX (a, b); } INLINE_FUN double GSL_MIN_DBL (double a, double b) { return GSL_MIN (a, b); } INLINE_FUN long double GSL_MAX_LDBL (long double a, long double b) { return GSL_MAX (a, b); } INLINE_FUN long double GSL_MIN_LDBL (long double a, long double b) { return GSL_MIN (a, b); } #else #define GSL_MAX_INT(a,b) GSL_MAX(a,b) #define GSL_MIN_INT(a,b) GSL_MIN(a,b) #define GSL_MAX_DBL(a,b) GSL_MAX(a,b) #define GSL_MIN_DBL(a,b) GSL_MIN(a,b) #define GSL_MAX_LDBL(a,b) GSL_MAX(a,b) #define GSL_MIN_LDBL(a,b) GSL_MIN(a,b) #endif /* HAVE_INLINE */ __END_DECLS #endif /* __GSL_POW_INT_H__ */ drc-3.2.2/source/gsl/c_pass_2.c0000644000076400001450000000577612616157443015223 0ustar denisitadm/* fft/c_pass_2.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_2) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]) { size_t i = 0, j = 0; size_t k, k1; const size_t factor = 2; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; const size_t jump = (factor - 1) * product_1; for (k = 0; k < q; k++) { ATOMIC w_real, w_imag; if (k == 0) { w_real = 1.0; w_imag = 0.0; } else { if (sign == gsl_fft_forward) { /* forward tranform */ w_real = GSL_REAL(twiddle[k - 1]); w_imag = GSL_IMAG(twiddle[k - 1]); } else { /* backward tranform: w -> conjugate(w) */ w_real = GSL_REAL(twiddle[k - 1]); w_imag = -GSL_IMAG(twiddle[k - 1]); } } for (k1 = 0; k1 < product_1; k1++) { const ATOMIC z0_real = REAL(in,istride,i); const ATOMIC z0_imag = IMAG(in,istride,i); const ATOMIC z1_real = REAL(in,istride,i+m); const ATOMIC z1_imag = IMAG(in,istride,i+m); /* compute x = W(2) z */ /* x0 = z0 + z1 */ const ATOMIC x0_real = z0_real + z1_real; const ATOMIC x0_imag = z0_imag + z1_imag; /* x1 = z0 - z1 */ const ATOMIC x1_real = z0_real - z1_real; const ATOMIC x1_imag = z0_imag - z1_imag; /* apply twiddle factors */ /* out0 = 1 * x0 */ REAL(out,ostride,j) = x0_real; IMAG(out,ostride,j) = x0_imag; /* out1 = w * x1 */ REAL(out,ostride,j+product_1) = w_real * x1_real - w_imag * x1_imag; IMAG(out,ostride,j+product_1) = w_real * x1_imag + w_imag * x1_real; i++; j++; } j += jump; } return 0; } drc-3.2.2/source/gsl/hc_radix2.c0000644000076400001450000001107413164705764015365 0ustar denisitadm/* fft/hc_radix2.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ int FUNCTION(gsl_fft_halfcomplex,radix2_backward) (BASE data[], const size_t stride, const size_t n) { int status = FUNCTION(gsl_fft_halfcomplex,radix2_transform) (data, stride, n) ; return status ; } int FUNCTION(gsl_fft_halfcomplex,radix2_inverse) (BASE data[], const size_t stride, const size_t n) { int status = FUNCTION(gsl_fft_halfcomplex,radix2_transform) (data, stride, n); if (status) { return status; } /* normalize inverse fft with 1/n */ { const ATOMIC norm = 1.0 / n; size_t i; for (i = 0; i < n; i++) { data[stride*i] *= norm; } } return status; } int FUNCTION(gsl_fft_halfcomplex,radix2_transform) (BASE data[], const size_t stride, const size_t n) { int result ; size_t p, p_1, q; size_t i; size_t logn = 0; int status; if (n == 1) /* identity operation */ { return 0 ; } /* make sure that n is a power of 2 */ result = fft_binary_logn(n) ; if (result == -1) { GSL_ERROR ("n is not a power of 2", GSL_EINVAL); } else { logn = result ; } /* apply fft recursion */ p = n; q = 1 ; p_1 = n/2 ; for (i = 1; i <= logn; i++) { size_t a, b; /* a = 0 */ for (b = 0; b < q; b++) { const ATOMIC z0 = VECTOR(data,stride,b*p); const ATOMIC z1 = VECTOR(data,stride,b*p + p_1); const ATOMIC t0_real = z0 + z1 ; const ATOMIC t1_real = z0 - z1 ; VECTOR(data,stride,b*p) = t0_real; VECTOR(data,stride,b*p + p_1) = t1_real ; } /* a = 1 ... p_{i-1}/2 - 1 */ { ATOMIC w_real = 1.0; ATOMIC w_imag = 0.0; const ATOMIC theta = 2.0 * M_PI / p; const ATOMIC s = sin (theta); const ATOMIC t = sin (theta / 2.0); const ATOMIC s2 = 2.0 * t * t; for (a = 1; a < (p_1)/2; a++) { /* trignometric recurrence for w-> exp(i theta) w */ { const ATOMIC tmp_real = w_real - s * w_imag - s2 * w_real; const ATOMIC tmp_imag = w_imag + s * w_real - s2 * w_imag; w_real = tmp_real; w_imag = tmp_imag; } for (b = 0; b < q; b++) { ATOMIC z0_real = VECTOR(data,stride,b*p + a) ; ATOMIC z0_imag = VECTOR(data,stride,b*p + p - a) ; ATOMIC z1_real = VECTOR(data,stride,b*p + p_1 - a) ; ATOMIC z1_imag = -VECTOR(data,stride,b*p + p_1 + a) ; /* t0 = z0 + z1 */ ATOMIC t0_real = z0_real + z1_real; ATOMIC t0_imag = z0_imag + z1_imag; /* t1 = (z0 - z1) */ ATOMIC t1_real = z0_real - z1_real; ATOMIC t1_imag = z0_imag - z1_imag; VECTOR(data,stride,b*p + a) = t0_real ; VECTOR(data,stride,b*p + p_1 - a) = t0_imag ; VECTOR(data,stride,b*p + p_1 + a) = (w_real * t1_real - w_imag * t1_imag) ; VECTOR(data,stride,b*p + p - a) = (w_real * t1_imag + w_imag * t1_real) ; } } } if (p_1 > 1) { for (b = 0; b < q; b++) { VECTOR(data,stride,b*p + p_1/2) *= 2 ; VECTOR(data,stride,b*p + p_1 + p_1/2) *= -2 ; } } p_1 = p_1 / 2 ; p = p / 2 ; q = q * 2 ; } /* bit reverse the ordering of output data for decimation in frequency algorithm */ status = FUNCTION(fft_real,bitreverse_order)(data, stride, n, logn) ; return status; } drc-3.2.2/source/gsl/gsl_pow_int.h0000644000076400001450000000437512616157443016055 0ustar denisitadm/* gsl_pow_int.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004, 2007 Gerard Jungman, Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_POW_INT_H__ #define __GSL_POW_INT_H__ #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS INLINE_DECL double gsl_pow_2(const double x); INLINE_DECL double gsl_pow_3(const double x); INLINE_DECL double gsl_pow_4(const double x); INLINE_DECL double gsl_pow_5(const double x); INLINE_DECL double gsl_pow_6(const double x); INLINE_DECL double gsl_pow_7(const double x); INLINE_DECL double gsl_pow_8(const double x); INLINE_DECL double gsl_pow_9(const double x); #ifdef HAVE_INLINE INLINE_FUN double gsl_pow_2(const double x) { return x*x; } INLINE_FUN double gsl_pow_3(const double x) { return x*x*x; } INLINE_FUN double gsl_pow_4(const double x) { double x2 = x*x; return x2*x2; } INLINE_FUN double gsl_pow_5(const double x) { double x2 = x*x; return x2*x2*x; } INLINE_FUN double gsl_pow_6(const double x) { double x2 = x*x; return x2*x2*x2; } INLINE_FUN double gsl_pow_7(const double x) { double x3 = x*x*x; return x3*x3*x; } INLINE_FUN double gsl_pow_8(const double x) { double x2 = x*x; double x4 = x2*x2; return x4*x4; } INLINE_FUN double gsl_pow_9(const double x) { double x3 = x*x*x; return x3*x3*x3; } #endif double gsl_pow_int(double x, int n); double gsl_pow_uint(double x, unsigned int n); __END_DECLS #endif /* __GSL_POW_INT_H__ */ drc-3.2.2/source/gsl/real_main.c0000644000076400001450000000761213164706175015451 0ustar denisitadm/* fft/real_main.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "real_pass.h" int FUNCTION(gsl_fft_real,transform) (BASE data[], const size_t stride, const size_t n, const TYPE(gsl_fft_real_wavetable) * wavetable, TYPE(gsl_fft_real_workspace) * work) { const size_t nf = wavetable->nf; size_t i; size_t product = 1; size_t tskip; size_t product_1; BASE *const scratch = work->scratch; TYPE(gsl_complex) *twiddle1, *twiddle2, *twiddle3, *twiddle4; size_t state = 0; BASE *in = data; size_t istride = stride ; BASE *out = scratch; size_t ostride = 1 ; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } if (n == 1) { /* FFT of one data point is the identity */ return 0; } if (n != wavetable->n) { GSL_ERROR ("wavetable does not match length of data", GSL_EINVAL); } if (n != work->n) { GSL_ERROR ("workspace does not match length of data", GSL_EINVAL); } for (i = 0; i < nf; i++) { const size_t factor = wavetable->factor[i]; product_1 = product; product *= factor; tskip = (product_1 + 1) / 2 - 1; if (state == 0) { in = data; istride = stride; out = scratch; ostride = 1; state = 1; } else { in = scratch; istride = 1; out = data; ostride = stride; state = 0; } if (factor == 2) { twiddle1 = wavetable->twiddle[i]; FUNCTION(fft_real,pass_2) (in, istride, out, ostride, product, n, twiddle1); } else if (factor == 3) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + tskip; FUNCTION(fft_real,pass_3) (in, istride, out, ostride, product, n, twiddle1, twiddle2); } else if (factor == 4) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + tskip; twiddle3 = twiddle2 + tskip; FUNCTION(fft_real,pass_4) (in, istride, out, ostride, product, n, twiddle1, twiddle2, twiddle3); } else if (factor == 5) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + tskip; twiddle3 = twiddle2 + tskip; twiddle4 = twiddle3 + tskip; FUNCTION(fft_real,pass_5) (in, istride, out, ostride, product, n, twiddle1, twiddle2, twiddle3, twiddle4); } else { twiddle1 = wavetable->twiddle[i]; FUNCTION(fft_real,pass_n) (in, istride, out, ostride, factor, product, n, twiddle1); } } if (state == 1) /* copy results back from scratch to data */ { for (i = 0; i < n; i++) { data[stride*i] = scratch[i] ; } } return 0; } drc-3.2.2/source/gsl/bitreverse.h0000644000076400001450000000250712616157443015676 0ustar denisitadm/* fft/bitreverse.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,bitreverse_order) (BASE data[], const size_t stride, const size_t n, size_t logn) ; static int FUNCTION(fft_real,bitreverse_order) (BASE data[], const size_t stride, const size_t n, size_t logn) ; drc-3.2.2/source/gsl/hc_pass_4.c0000644000076400001450000001456413164706040015360 0ustar denisitadm/* fft/hc_pass_4.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_halfcomplex,pass_4) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[]) { size_t k, k1; size_t factor, q, m, product_1; factor = 4; m = n / factor; q = n / product; product_1 = product / factor; for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 4 * k1 * q; const size_t from1 = from0 + 2 * q - 1; const size_t from2 = from1 + 2 * q; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC t1_real = z0_real + z2_real; const ATOMIC t2_real = 2 * z1_real; const ATOMIC t3_real = z0_real - z2_real; const ATOMIC t4_imag = 2 * z1_imag; const size_t to0 = q * k1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; const size_t to3 = to2 + m; VECTOR(out,ostride,to0) = t1_real + t2_real; VECTOR(out,ostride,to1) = t3_real - t4_imag; VECTOR(out,ostride,to2) = t1_real - t2_real; VECTOR(out,ostride,to3) = t3_real + t4_imag; } if (q == 1) return; for (k = 1; k < (q + 1) / 2; k++) { const ATOMIC w1_real = GSL_REAL(twiddle1[k - 1]); const ATOMIC w1_imag = GSL_IMAG(twiddle1[k - 1]); const ATOMIC w2_real = GSL_REAL(twiddle2[k - 1]); const ATOMIC w2_imag = GSL_IMAG(twiddle2[k - 1]); const ATOMIC w3_real = GSL_REAL(twiddle3[k - 1]); const ATOMIC w3_imag = GSL_IMAG(twiddle3[k - 1]); for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 4 * k1 * q + 2 * k - 1; const size_t from1 = from0 + 2 * q; const size_t from2 = 4 * k1 * q - 2 * k + 2 * q - 1; const size_t from3 = from2 + 2 * q; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC z2_real = VECTOR(in,istride,from3); const ATOMIC z2_imag = -VECTOR(in,istride,from3 + 1); const ATOMIC z3_real = VECTOR(in,istride,from2); const ATOMIC z3_imag = -VECTOR(in,istride,from2 + 1); /* compute x = W(4) z */ /* t1 = z0 + z2 */ const ATOMIC t1_real = z0_real + z2_real; const ATOMIC t1_imag = z0_imag + z2_imag; /* t2 = z1 + z3 */ const ATOMIC t2_real = z1_real + z3_real; const ATOMIC t2_imag = z1_imag + z3_imag; /* t3 = z0 - z2 */ const ATOMIC t3_real = z0_real - z2_real; const ATOMIC t3_imag = z0_imag - z2_imag; /* t4 = (z1 - z3) */ const ATOMIC t4_real = (z1_real - z3_real); const ATOMIC t4_imag = (z1_imag - z3_imag); /* x0 = t1 + t2 */ const ATOMIC x0_real = t1_real + t2_real; const ATOMIC x0_imag = t1_imag + t2_imag; /* x1 = t3 + i t4 */ const ATOMIC x1_real = t3_real - t4_imag; const ATOMIC x1_imag = t3_imag + t4_real; /* x2 = t1 - t2 */ const ATOMIC x2_real = t1_real - t2_real; const ATOMIC x2_imag = t1_imag - t2_imag; /* x3 = t3 - i t4 */ const ATOMIC x3_real = t3_real + t4_imag; const ATOMIC x3_imag = t3_imag - t4_real; const size_t to0 = k1 * q + 2 * k - 1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; const size_t to3 = to2 + m; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; VECTOR(out,ostride,to1) = w1_real * x1_real - w1_imag * x1_imag; VECTOR(out,ostride,to1 + 1) = w1_imag * x1_real + w1_real * x1_imag; VECTOR(out,ostride,to2) = w2_real * x2_real - w2_imag * x2_imag; VECTOR(out,ostride,to2 + 1) = w2_imag * x2_real + w2_real * x2_imag; /* to3 = w3 * x3 */ VECTOR(out,ostride,to3) = w3_real * x3_real - w3_imag * x3_imag; VECTOR(out,ostride,to3 + 1) = w3_real * x3_imag + w3_imag * x3_real; } } if (q % 2 == 1) return; for (k1 = 0; k1 < product_1; k1++) { const size_t from0 = 4 * k1 * q + q - 1; const size_t from1 = from0 + 2 * q; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC t1_real = sqrt (2.0) * (z0_imag + z1_imag); const ATOMIC t2_real = sqrt (2.0) * (z0_real - z1_real); const ATOMIC x0_real = 2 * (z0_real + z1_real); const ATOMIC x1_real = t2_real - t1_real; const ATOMIC x2_real = 2 * (z1_imag - z0_imag); const ATOMIC x3_real = -(t2_real + t1_real); const size_t to0 = k1 * q + q - 1; const size_t to1 = to0 + m; const size_t to2 = to1 + m; const size_t to3 = to2 + m; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to2) = x2_real; VECTOR(out,ostride,to3) = x3_real; } return; } drc-3.2.2/source/gsl/gsl_fft_halfcomplex.h0000644000076400001450000000572412616157443017536 0ustar denisitadm/* fft/gsl_fft_halfcomplex.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_FFT_HALFCOMPLEX_H__ #define __GSL_FFT_HALFCOMPLEX_H__ #include #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS int gsl_fft_halfcomplex_radix2_backward (double data[], const size_t stride, const size_t n); int gsl_fft_halfcomplex_radix2_inverse (double data[], const size_t stride, const size_t n); int gsl_fft_halfcomplex_radix2_transform (double data[], const size_t stride, const size_t n); typedef struct { size_t n; size_t nf; size_t factor[64]; gsl_complex *twiddle[64]; gsl_complex *trig; } gsl_fft_halfcomplex_wavetable; gsl_fft_halfcomplex_wavetable * gsl_fft_halfcomplex_wavetable_alloc (size_t n); void gsl_fft_halfcomplex_wavetable_free (gsl_fft_halfcomplex_wavetable * wavetable); int gsl_fft_halfcomplex_backward (double data[], const size_t stride, const size_t n, const gsl_fft_halfcomplex_wavetable * wavetable, gsl_fft_real_workspace * work); int gsl_fft_halfcomplex_inverse (double data[], const size_t stride, const size_t n, const gsl_fft_halfcomplex_wavetable * wavetable, gsl_fft_real_workspace * work); int gsl_fft_halfcomplex_transform (double data[], const size_t stride, const size_t n, const gsl_fft_halfcomplex_wavetable * wavetable, gsl_fft_real_workspace * work); int gsl_fft_halfcomplex_unpack (const double halfcomplex_coefficient[], double complex_coefficient[], const size_t stride, const size_t n); int gsl_fft_halfcomplex_radix2_unpack (const double halfcomplex_coefficient[], double complex_coefficient[], const size_t stride, const size_t n); __END_DECLS #endif /* __GSL_FFT_HALFCOMPLEX_H__ */ drc-3.2.2/source/gsl/real_pass_n.c0000644000076400001450000002052212616157443016002 0ustar denisitadm/* fft/real_pass_n.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_real,pass_n) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t factor, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]) { size_t k, k1; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; size_t e1, e2; const double d_theta = 2.0 * M_PI / ((double) factor); const ATOMIC cos_d_theta = cos (d_theta); const ATOMIC sin_d_theta = sin (d_theta); for (k1 = 0; k1 < q; k1++) { /* compute x = W(factor) z, for z real */ ATOMIC dw_real = 1.0, dw_imag = 0.0; for (e1 = 0; e1 <= factor - e1; e1++) { ATOMIC sum_real = 0.0; ATOMIC sum_imag = 0.0; ATOMIC w_real = 1.0, w_imag = 0.0; if (e1 > 0) { ATOMIC tmp_real = dw_real * cos_d_theta + dw_imag * sin_d_theta; ATOMIC tmp_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta; dw_real = tmp_real; dw_imag = tmp_imag; } for (e2 = 0; e2 < factor; e2++) { ATOMIC z_real = VECTOR(in,istride,k1 * product_1 + e2 * m); if (e2 > 0) { ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag; ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real; w_real = tmp_real; w_imag = tmp_imag; } sum_real += w_real * z_real; sum_imag += w_imag * z_real; } if (e1 == 0) { const size_t to0 = product * k1; VECTOR(out,ostride,to0) = sum_real; } else if (e1 < factor - e1) { const size_t to0 = k1 * product + 2 * e1 * product_1 - 1; VECTOR(out,ostride,to0) = sum_real; VECTOR(out,ostride,to0 + 1) = sum_imag; } else if (e1 == factor - e1) { const size_t to0 = k1 * product + 2 * e1 * product_1 - 1; VECTOR(out,ostride,to0) = sum_real; } } } if (product_1 == 1) return; for (k = 1; k < (product_1 + 1) / 2; k++) { for (k1 = 0; k1 < q; k1++) { ATOMIC dw_real = 1.0, dw_imag = 0.0; for (e1 = 0; e1 < factor; e1++) { ATOMIC sum_real = 0.0, sum_imag = 0.0; ATOMIC w_real = 1.0, w_imag = 0.0; if (e1 > 0) { const ATOMIC tmp_real = dw_real * cos_d_theta + dw_imag * sin_d_theta; const ATOMIC tmp_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta; dw_real = tmp_real; dw_imag = tmp_imag; } for (e2 = 0; e2 < factor; e2++) { int tskip = (product_1 + 1) / 2 - 1; const size_t from0 = k1 * product_1 + 2 * k + e2 * m - 1; ATOMIC tw_real, tw_imag; ATOMIC z_real, z_imag; if (e2 == 0) { tw_real = 1.0; tw_imag = 0.0; } else { const size_t t_index = (k - 1) + (e2 - 1) * tskip; tw_real = GSL_REAL(twiddle[t_index]); tw_imag = -GSL_IMAG(twiddle[t_index]); } { const ATOMIC f0_real = VECTOR(in,istride,from0); const ATOMIC f0_imag = VECTOR(in,istride,from0 + 1); z_real = tw_real * f0_real - tw_imag * f0_imag; z_imag = tw_real * f0_imag + tw_imag * f0_real; } if (e2 > 0) { const ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag; const ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real; w_real = tmp_real; w_imag = tmp_imag; } sum_real += w_real * z_real - w_imag * z_imag; sum_imag += w_real * z_imag + w_imag * z_real; } if (e1 < factor - e1) { const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k; VECTOR(out,ostride,to0) = sum_real; VECTOR(out,ostride,to0 + 1) = sum_imag; } else { const size_t to0 = k1 * product - 1 + 2 * (factor - e1) * product_1 - 2 * k; VECTOR(out,ostride,to0) = sum_real; VECTOR(out,ostride,to0 + 1) = -sum_imag; } } } } if (product_1 % 2 == 1) return; { double tw_arg = M_PI / ((double) factor); ATOMIC cos_tw_arg = cos (tw_arg); ATOMIC sin_tw_arg = -sin (tw_arg); for (k1 = 0; k1 < q; k1++) { ATOMIC dw_real = 1.0, dw_imag = 0.0; for (e1 = 0; e1 < factor; e1++) { ATOMIC z_real, z_imag; ATOMIC sum_real = 0.0; ATOMIC sum_imag = 0.0; ATOMIC w_real = 1.0, w_imag = 0.0; ATOMIC tw_real = 1.0, tw_imag = 0.0; if (e1 > 0) { ATOMIC t_real = dw_real * cos_d_theta + dw_imag * sin_d_theta; ATOMIC t_imag = -dw_real * sin_d_theta + dw_imag * cos_d_theta; dw_real = t_real; dw_imag = t_imag; } for (e2 = 0; e2 < factor; e2++) { if (e2 > 0) { ATOMIC tmp_real = tw_real * cos_tw_arg - tw_imag * sin_tw_arg; ATOMIC tmp_imag = tw_real * sin_tw_arg + tw_imag * cos_tw_arg; tw_real = tmp_real; tw_imag = tmp_imag; } if (e2 > 0) { ATOMIC tmp_real = dw_real * w_real - dw_imag * w_imag; ATOMIC tmp_imag = dw_real * w_imag + dw_imag * w_real; w_real = tmp_real; w_imag = tmp_imag; } { const size_t from0 = k1 * product_1 + 2 * k + e2 * m - 1; const ATOMIC f0_real = VECTOR(in,istride,from0); z_real = tw_real * f0_real; z_imag = tw_imag * f0_real; } sum_real += w_real * z_real - w_imag * z_imag; sum_imag += w_real * z_imag + w_imag * z_real; } if (e1 + 1 < factor - e1) { const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k; VECTOR(out,ostride,to0) = sum_real; VECTOR(out,ostride,to0 + 1) = sum_imag; } else if (e1 + 1 == factor - e1) { const size_t to0 = k1 * product - 1 + 2 * e1 * product_1 + 2 * k; VECTOR(out,ostride,to0) = sum_real; } else { const size_t to0 = k1 * product - 1 + 2 * (factor - e1) * product_1 - 2 * k; VECTOR(out,ostride,to0) = sum_real; VECTOR(out,ostride,to0 + 1) = -sum_imag; } } } } return; } drc-3.2.2/source/gsl/c_pass_n.c0000644000076400001450000001374012616157443015305 0ustar denisitadm/* fft/c_pass_n.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_n) (BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t factor, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]) { size_t i = 0, j = 0; size_t k, k1; const size_t m = n / factor; const size_t q = n / product; const size_t p_1 = product / factor; const size_t jump = (factor - 1) * p_1; size_t e, e1; for (i = 0; i < m; i++) { REAL(out,ostride,i) = REAL(in,istride,i); IMAG(out,ostride,i) = IMAG(in,istride,i); } for (e = 1; e < (factor - 1) / 2 + 1; e++) { for (i = 0; i < m; i++) { const size_t idx = i + e * m; const size_t idxc = i + (factor - e) * m; REAL(out,ostride,idx) = REAL(in,istride,idx) + REAL(in,istride,idxc); IMAG(out,ostride,idx) = IMAG(in,istride,idx) + IMAG(in,istride,idxc); REAL(out,ostride,idxc) = REAL(in,istride,idx) - REAL(in,istride,idxc); IMAG(out,ostride,idxc) = IMAG(in,istride,idx) - IMAG(in,istride,idxc); } } /* e = 0 */ for (i=0 ; i #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS enum { GSL_SUCCESS = 0, GSL_FAILURE = -1, GSL_CONTINUE = -2, /* iteration has not converged */ GSL_EDOM = 1, /* input domain error, e.g sqrt(-1) */ GSL_ERANGE = 2, /* output range error, e.g. exp(1e100) */ GSL_EFAULT = 3, /* invalid pointer */ GSL_EINVAL = 4, /* invalid argument supplied by user */ GSL_EFAILED = 5, /* generic failure */ GSL_EFACTOR = 6, /* factorization failed */ GSL_ESANITY = 7, /* sanity check failed - shouldn't happen */ GSL_ENOMEM = 8, /* malloc failed */ GSL_EBADFUNC = 9, /* problem with user-supplied function */ GSL_ERUNAWAY = 10, /* iterative process is out of control */ GSL_EMAXITER = 11, /* exceeded max number of iterations */ GSL_EZERODIV = 12, /* tried to divide by zero */ GSL_EBADTOL = 13, /* user specified an invalid tolerance */ GSL_ETOL = 14, /* failed to reach the specified tolerance */ GSL_EUNDRFLW = 15, /* underflow */ GSL_EOVRFLW = 16, /* overflow */ GSL_ELOSS = 17, /* loss of accuracy */ GSL_EROUND = 18, /* failed because of roundoff error */ GSL_EBADLEN = 19, /* matrix, vector lengths are not conformant */ GSL_ENOTSQR = 20, /* matrix not square */ GSL_ESING = 21, /* apparent singularity detected */ GSL_EDIVERGE = 22, /* integral or series is divergent */ GSL_EUNSUP = 23, /* requested feature is not supported by the hardware */ GSL_EUNIMPL = 24, /* requested feature not (yet) implemented */ GSL_ECACHE = 25, /* cache limit exceeded */ GSL_ETABLE = 26, /* table limit exceeded */ GSL_ENOPROG = 27, /* iteration is not making progress towards solution */ GSL_ENOPROGJ = 28, /* jacobian evaluations are not improving the solution */ GSL_ETOLF = 29, /* cannot reach the specified tolerance in F */ GSL_ETOLX = 30, /* cannot reach the specified tolerance in X */ GSL_ETOLG = 31, /* cannot reach the specified tolerance in gradient */ GSL_EOF = 32 /* end of file */ } ; void gsl_error (const char * reason, const char * file, int line, int gsl_errno); void gsl_stream_printf (const char *label, const char *file, int line, const char *reason); const char * gsl_strerror (const int gsl_errno); typedef void gsl_error_handler_t (const char * reason, const char * file, int line, int gsl_errno); typedef void gsl_stream_handler_t (const char * label, const char * file, int line, const char * reason); gsl_error_handler_t * gsl_set_error_handler (gsl_error_handler_t * new_handler); gsl_error_handler_t * gsl_set_error_handler_off (void); gsl_stream_handler_t * gsl_set_stream_handler (gsl_stream_handler_t * new_handler); FILE * gsl_set_stream (FILE * new_stream); /* GSL_ERROR: call the error handler, and return the error code */ #define GSL_ERROR(reason, gsl_errno) \ do { \ gsl_error (reason, __FILE__, __LINE__, gsl_errno) ; \ return gsl_errno ; \ } while (0) /* GSL_ERROR_VAL: call the error handler, and return the given value */ #define GSL_ERROR_VAL(reason, gsl_errno, value) \ do { \ gsl_error (reason, __FILE__, __LINE__, gsl_errno) ; \ return value ; \ } while (0) /* GSL_ERROR_VOID: call the error handler, and then return (for void functions which still need to generate an error) */ #define GSL_ERROR_VOID(reason, gsl_errno) \ do { \ gsl_error (reason, __FILE__, __LINE__, gsl_errno) ; \ return ; \ } while (0) /* GSL_ERROR_NULL suitable for out-of-memory conditions */ #define GSL_ERROR_NULL(reason, gsl_errno) GSL_ERROR_VAL(reason, gsl_errno, 0) /* Sometimes you have several status results returned from * function calls and you want to combine them in some sensible * way. You cannot produce a "total" status condition, but you can * pick one from a set of conditions based on an implied hierarchy. * * In other words: * you have: status_a, status_b, ... * you want: status = (status_a if it is bad, or status_b if it is bad,...) * * In this example you consider status_a to be more important and * it is checked first, followed by the others in the order specified. * * Here are some dumb macros to do this. */ #define GSL_ERROR_SELECT_2(a,b) ((a) != GSL_SUCCESS ? (a) : ((b) != GSL_SUCCESS ? (b) : GSL_SUCCESS)) #define GSL_ERROR_SELECT_3(a,b,c) ((a) != GSL_SUCCESS ? (a) : GSL_ERROR_SELECT_2(b,c)) #define GSL_ERROR_SELECT_4(a,b,c,d) ((a) != GSL_SUCCESS ? (a) : GSL_ERROR_SELECT_3(b,c,d)) #define GSL_ERROR_SELECT_5(a,b,c,d,e) ((a) != GSL_SUCCESS ? (a) : GSL_ERROR_SELECT_4(b,c,d,e)) #define GSL_STATUS_UPDATE(sp, s) do { if ((s) != GSL_SUCCESS) *(sp) = (s);} while(0) __END_DECLS #endif /* __GSL_ERRNO_H__ */ drc-3.2.2/source/gsl/complex_internal.h0000644000076400001450000000055612616157443017071 0ustar denisitadm/* Handling of packed complex types... not meant for client consumption. */ #ifndef COMPLEX_INTERNAL_H_ #define COMPLEX_INTERNAL_H_ #define VECTOR(a,stride,i) ((a)[(stride)*(i)]) #define REAL(a,stride,i) ((a)[2*(stride)*(i)]) #define IMAG(a,stride,i) ((a)[2*(stride)*(i)+1]) #define REAL0(a) ((a)[0]) #define IMAG0(a) ((a)[1]) #endif /* !COMPLEX_INTERNAL_H_ */ drc-3.2.2/source/gsl/gsl_dft_complex.h0000644000076400001450000000342612616157443016676 0ustar denisitadm/* fft/gsl_dft_complex.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_DFT_COMPLEX_H__ #define __GSL_DFT_COMPLEX_H__ #include #include #include #include #undef __BEGIN_DECLS #undef __END_DECLS #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { # define __END_DECLS } #else # define __BEGIN_DECLS /* empty */ # define __END_DECLS /* empty */ #endif __BEGIN_DECLS int gsl_dft_complex_forward (const double data[], const size_t stride, const size_t n, double result[]); int gsl_dft_complex_backward (const double data[], const size_t stride, const size_t n, double result[]); int gsl_dft_complex_inverse (const double data[], const size_t stride, const size_t n, double result[]); int gsl_dft_complex_transform (const double data[], const size_t stride, const size_t n, double result[], const gsl_fft_direction sign); __END_DECLS #endif /* __GSL_DFT_COMPLEX_H__ */ drc-3.2.2/source/gsl/real_pass_4.c0000644000076400001450000001604512616157443015715 0ustar denisitadm/* fft/real_pass_4.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_real,pass_4) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[]) { size_t k, k1; const size_t factor = 4; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const size_t from3 = from2 + m; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC z3_real = VECTOR(in,istride,from3); /* compute x = W(4) z */ /* t1 = z0 + z2 */ const ATOMIC t1_real = z0_real + z2_real; /* t2 = z1 + z3 */ const ATOMIC t2_real = z1_real + z3_real; /* t3 = z0 - z2 */ const ATOMIC t3_real = z0_real - z2_real; /* t4 = - (z1 - z3) */ const ATOMIC t4_real = -(z1_real - z3_real); /* x0 = t1 + t2 */ const ATOMIC x0_real = t1_real + t2_real; /* x1 = t3 + i t4 */ const ATOMIC x1_real = t3_real; const ATOMIC x1_imag = t4_real; /* x2 = t1 - t2 */ const ATOMIC x2_real = t1_real - t2_real; const size_t to0 = product * k1; const size_t to1 = to0 + 2 * product_1 - 1; const size_t to2 = to1 + 2 * product_1; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to1 + 1) = x1_imag; VECTOR(out,ostride,to2) = x2_real; } if (product_1 == 1) return; for (k = 1; k < (product_1 + 1) / 2; k++) { ATOMIC w1_real, w1_imag, w2_real, w2_imag, w3_real, w3_imag; w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = -GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = -GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = -GSL_IMAG(twiddle3[k - 1]); for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + 2 * k - 1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const size_t from3 = from2 + m; const ATOMIC f0_real = VECTOR(in,istride,from0); const ATOMIC f0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC f1_real = VECTOR(in,istride,from1); const ATOMIC f1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC f2_real = VECTOR(in,istride,from2); const ATOMIC f2_imag = VECTOR(in,istride,from2 + 1); const ATOMIC f3_real = VECTOR(in,istride,from3); const ATOMIC f3_imag = VECTOR(in,istride,from3 + 1); const ATOMIC z0_real = f0_real; const ATOMIC z0_imag = f0_imag; const ATOMIC z1_real = w1_real * f1_real - w1_imag * f1_imag; const ATOMIC z1_imag = w1_real * f1_imag + w1_imag * f1_real; const ATOMIC z2_real = w2_real * f2_real - w2_imag * f2_imag; const ATOMIC z2_imag = w2_real * f2_imag + w2_imag * f2_real; const ATOMIC z3_real = w3_real * f3_real - w3_imag * f3_imag; const ATOMIC z3_imag = w3_real * f3_imag + w3_imag * f3_real; /* compute x = W(4) z */ /* t1 = z0 + z2 */ const ATOMIC t1_real = z0_real + z2_real; const ATOMIC t1_imag = z0_imag + z2_imag; /* t2 = z1 + z3 */ const ATOMIC t2_real = z1_real + z3_real; const ATOMIC t2_imag = z1_imag + z3_imag; /* t3 = z0 - z2 */ const ATOMIC t3_real = z0_real - z2_real; const ATOMIC t3_imag = z0_imag - z2_imag; /* t4 = - (z1 - z3) */ const ATOMIC t4_real = -(z1_real - z3_real); const ATOMIC t4_imag = -(z1_imag - z3_imag); /* x0 = t1 + t2 */ const ATOMIC x0_real = t1_real + t2_real; const ATOMIC x0_imag = t1_imag + t2_imag; /* x1 = t3 + i t4 */ const ATOMIC x1_real = t3_real - t4_imag; const ATOMIC x1_imag = t3_imag + t4_real; /* x2 = t1 - t2 */ const ATOMIC x2_real = t1_real - t2_real; const ATOMIC x2_imag = t1_imag - t2_imag; /* x3 = t3 - i t4 */ const ATOMIC x3_real = t3_real + t4_imag; const ATOMIC x3_imag = t3_imag - t4_real; const size_t to0 = k1 * product + 2 * k - 1; const size_t to1 = to0 + 2 * product_1; const size_t to2 = 2 * product_1 - 2 * k + k1 * product - 1; const size_t to3 = to2 + 2 * product_1; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to1 + 1) = x1_imag; VECTOR(out,ostride,to3) = x2_real; VECTOR(out,ostride,to3 + 1) = -x2_imag; VECTOR(out,ostride,to2) = x3_real; VECTOR(out,ostride,to2 + 1) = -x3_imag; } } if (product_1 % 2 == 1) return; for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + product_1 - 1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const size_t from3 = from2 + m; const ATOMIC x0 = VECTOR(in,istride,from0); const ATOMIC x1 = VECTOR(in,istride,from1); const ATOMIC x2 = VECTOR(in,istride,from2); const ATOMIC x3 = VECTOR(in,istride,from3); const ATOMIC t1 = (1.0 / sqrt (2.0)) * (x1 - x3); const ATOMIC t2 = (1.0 / sqrt (2.0)) * (x1 + x3); const size_t to0 = k1 * product + 2 * k - 1; const size_t to1 = to0 + 2 * product_1; VECTOR(out,ostride,to0) = x0 + t1; VECTOR(out,ostride,to0 + 1) = -x2 - t2; VECTOR(out,ostride,to1) = x0 - t1; VECTOR(out,ostride,to1 + 1) = x2 - t2; } return; } drc-3.2.2/source/gsl/c_pass_4.c0000644000076400001450000001221512616157443015207 0ustar denisitadm/* fft/c_pass_4.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_4) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[]) { size_t i = 0, j = 0; size_t k, k1; const size_t factor = 4; const size_t m = n / factor; const size_t q = n / product; const size_t p_1 = product / factor; const size_t jump = (factor - 1) * p_1; for (k = 0; k < q; k++) { ATOMIC w1_real, w1_imag, w2_real, w2_imag, w3_real, w3_imag; if (k == 0) { w1_real = 1.0; w1_imag = 0.0; w2_real = 1.0; w2_imag = 0.0; w3_real = 1.0; w3_imag = 0.0; } else { if (sign == gsl_fft_forward) { /* forward tranform */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = GSL_IMAG(twiddle3[k - 1]); } else { /* backward tranform: w -> conjugate(w) */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = -GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = -GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = -GSL_IMAG(twiddle3[k - 1]); } } for (k1 = 0; k1 < p_1; k1++) { const ATOMIC z0_real = REAL(in,istride,i); const ATOMIC z0_imag = IMAG(in,istride,i); const ATOMIC z1_real = REAL(in,istride,i+m); const ATOMIC z1_imag = IMAG(in,istride,i+m); const ATOMIC z2_real = REAL(in,istride,i+2*m); const ATOMIC z2_imag = IMAG(in,istride,i+2*m); const ATOMIC z3_real = REAL(in,istride,i+3*m); const ATOMIC z3_imag = IMAG(in,istride,i+3*m); /* compute x = W(4) z */ /* t1 = z0 + z2 */ const ATOMIC t1_real = z0_real + z2_real; const ATOMIC t1_imag = z0_imag + z2_imag; /* t2 = z1 + z3 */ const ATOMIC t2_real = z1_real + z3_real; const ATOMIC t2_imag = z1_imag + z3_imag; /* t3 = z0 - z2 */ const ATOMIC t3_real = z0_real - z2_real; const ATOMIC t3_imag = z0_imag - z2_imag; /* t4 = (+/-) (z1 - z3) */ const ATOMIC t4_real = ((int) sign) * (z1_real - z3_real); const ATOMIC t4_imag = ((int) sign) * (z1_imag - z3_imag); /* x0 = t1 + t2 */ const ATOMIC x0_real = t1_real + t2_real; const ATOMIC x0_imag = t1_imag + t2_imag; /* x1 = t3 + i t4 */ const ATOMIC x1_real = t3_real - t4_imag; const ATOMIC x1_imag = t3_imag + t4_real; /* x2 = t1 - t2 */ const ATOMIC x2_real = t1_real - t2_real; const ATOMIC x2_imag = t1_imag - t2_imag; /* x3 = t3 - i t4 */ const ATOMIC x3_real = t3_real + t4_imag; const ATOMIC x3_imag = t3_imag - t4_real; /* apply twiddle factors */ /* to0 = 1 * x0 */ REAL(out,ostride,j) = x0_real; IMAG(out,ostride,j) = x0_imag; /* to1 = w1 * x1 */ REAL(out, ostride, j + p_1) = w1_real * x1_real - w1_imag * x1_imag; IMAG(out, ostride, j + p_1) = w1_real * x1_imag + w1_imag * x1_real; /* to2 = w2 * x2 */ REAL(out, ostride, j + 2 * p_1) = w2_real * x2_real - w2_imag * x2_imag; IMAG(out, ostride, j + 2 * p_1) = w2_real * x2_imag + w2_imag * x2_real; /* to3 = w3 * x3 */ REAL(out, ostride, j + 3 * p_1) = w3_real * x3_real - w3_imag * x3_imag; IMAG(out, ostride, j + 3 * p_1) = w3_real * x3_imag + w3_imag * x3_real; i++; j++; } j += jump; } return 0; } drc-3.2.2/source/gsl/c_pass_3.c0000644000076400001450000001050712616157443015210 0ustar denisitadm/* fft/c_pass_3.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_3) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) * twiddle1, const TYPE(gsl_complex) * twiddle2) { size_t i = 0, j = 0; size_t k, k1; const size_t factor = 3; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; const size_t jump = (factor - 1) * product_1; const ATOMIC tau = sqrt (3.0) / 2.0; for (k = 0; k < q; k++) { ATOMIC w1_real, w1_imag, w2_real, w2_imag; if (k == 0) { w1_real = 1.0; w1_imag = 0.0; w2_real = 1.0; w2_imag = 0.0; } else { if (sign == gsl_fft_forward) { /* forward tranform */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = GSL_IMAG(twiddle2[k - 1]); } else { /* backward tranform: w -> conjugate(w) */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = -GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = -GSL_IMAG(twiddle2[k - 1]); } } for (k1 = 0; k1 < product_1; k1++) { const ATOMIC z0_real = REAL(in,istride,i); const ATOMIC z0_imag = IMAG(in,istride,i); const ATOMIC z1_real = REAL(in,istride,i+m); const ATOMIC z1_imag = IMAG(in,istride,i+m); const ATOMIC z2_real = REAL(in,istride,i+2*m); const ATOMIC z2_imag = IMAG(in,istride,i+2*m); /* compute x = W(3) z */ /* t1 = z1 + z2 */ const ATOMIC t1_real = z1_real + z2_real; const ATOMIC t1_imag = z1_imag + z2_imag; /* t2 = z0 - t1/2 */ const ATOMIC t2_real = z0_real - t1_real / 2.0; const ATOMIC t2_imag = z0_imag - t1_imag / 2.0; /* t3 = (+/-) sin(pi/3)*(z1 - z2) */ const ATOMIC t3_real = ((int) sign) * tau * (z1_real - z2_real); const ATOMIC t3_imag = ((int) sign) * tau * (z1_imag - z2_imag); /* x0 = z0 + t1 */ const ATOMIC x0_real = z0_real + t1_real; const ATOMIC x0_imag = z0_imag + t1_imag; /* x1 = t2 + i t3 */ const ATOMIC x1_real = t2_real - t3_imag; const ATOMIC x1_imag = t2_imag + t3_real; /* x2 = t2 - i t3 */ const ATOMIC x2_real = t2_real + t3_imag; const ATOMIC x2_imag = t2_imag - t3_real; /* apply twiddle factors */ /* to0 = 1 * x0 */ REAL(out,ostride,j) = x0_real; IMAG(out,ostride,j) = x0_imag; /* to1 = w1 * x1 */ REAL(out,ostride,j+product_1) = w1_real * x1_real - w1_imag * x1_imag; IMAG(out,ostride,j+product_1) = w1_real * x1_imag + w1_imag * x1_real; /* to2 = w2 * x2 */ REAL(out,ostride,j+2*product_1) = w2_real * x2_real - w2_imag * x2_imag; IMAG(out,ostride,j+2*product_1) = w2_real * x2_imag + w2_imag * x2_real; i++; j++; } j += jump; } return 0; } drc-3.2.2/source/gsl/factorize.h0000644000076400001450000000232112616157443015504 0ustar denisitadm/* fft/factorize.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int fft_complex_factorize (const size_t n, size_t *nf, size_t factors[]); static int fft_halfcomplex_factorize (const size_t n, size_t *nf, size_t factors[]); static int fft_real_factorize (const size_t n, size_t *nf, size_t factors[]); static int fft_factorize (const size_t n, const size_t implemented_subtransforms[], size_t *n_factors, size_t factors[]); static int fft_binary_logn (const size_t n) ; drc-3.2.2/source/gsl/gsl_inline.h0000644000076400001450000000463712616157443015655 0ustar denisitadm/* gsl_inline.h * * Copyright (C) 2008, 2009 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_INLINE_H__ #define __GSL_INLINE_H__ /* In recent versiions of GCC, the inline keyword has two different forms: GNU and C99. In GNU mode we can use 'extern inline' to make inline functions work like macros. The function is only inlined--it is never output as a definition in an object file. In the new C99 mode 'extern inline' has a different meaning--it causes the definition of the function to be output in each object file where it is used. This will result in multiple-definition errors on linking. The 'inline' keyword on its own (without extern) has the same behavior as the original GNU 'extern inline'. The C99 style is the default with -std=c99 in GCC 4.3. This header file allows either form of inline to be used by redefining the macros INLINE_DECL and INLINE_FUN. These are used in the public header files as INLINE_DECL double gsl_foo (double x); #ifdef HAVE_INLINE INLINE_FUN double gsl_foo (double x) { return x+1.0; } ; #endif */ #ifdef HAVE_INLINE # if defined(__GNUC_STDC_INLINE__) || defined(GSL_C99_INLINE) || defined(HAVE_C99_INLINE) # define INLINE_DECL inline /* use C99 inline */ # define INLINE_FUN inline # else # define INLINE_DECL /* use GNU extern inline */ # define INLINE_FUN extern inline # endif #else # define INLINE_DECL /* */ #endif /* Range checking conditions in headers do not require any run-time tests of the global variable gsl_check_range. They are enabled or disabled in user code at compile time with GSL_RANGE_CHECK macro. See also build.h. */ #define GSL_RANGE_COND(x) (x) #endif /* __GSL_INLINE_H__ */ drc-3.2.2/source/gsl/real_unpack.c0000644000076400001450000000245412616157443016004 0ustar denisitadm/* fft/real_unpack.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "complex_internal.h" int FUNCTION(gsl_fft_real,unpack) (const BASE real_coefficient[], BASE complex_coefficient[], const size_t stride, const size_t n) { size_t i; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } for (i = 0; i < n; i++) { REAL(complex_coefficient,stride,i) = real_coefficient[i * stride]; IMAG(complex_coefficient,stride,i) = 0.0; } return 0; } drc-3.2.2/source/gsl/c_pass_6.c0000644000076400001450000002023112616157443015206 0ustar denisitadm/* fft/c_pass_6.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static int FUNCTION(fft_complex,pass_6) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const gsl_fft_direction sign, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[], const TYPE(gsl_complex) twiddle5[]) { size_t i = 0, j = 0; size_t k, k1; const size_t factor = 6; const size_t m = n / factor; const size_t q = n / product; const size_t p_1 = product / factor; const size_t jump = (factor - 1) * p_1; const ATOMIC tau = sqrt (3.0) / 2.0; for (k = 0; k < q; k++) { ATOMIC w1_real, w1_imag, w2_real, w2_imag, w3_real, w3_imag, w4_real, w4_imag, w5_real, w5_imag; if (k == 0) { w1_real = 1.0; w1_imag = 0.0; w2_real = 1.0; w2_imag = 0.0; w3_real = 1.0; w3_imag = 0.0; w4_real = 1.0; w4_imag = 0.0; w5_real = 1.0; w5_imag = 0.0; } else { if (sign == gsl_fft_forward) { /* forward tranform */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = GSL_IMAG(twiddle3[k - 1]); w4_real = GSL_REAL(twiddle4[k - 1]); w4_imag = GSL_IMAG(twiddle4[k - 1]); w5_real = GSL_REAL(twiddle5[k - 1]); w5_imag = GSL_IMAG(twiddle5[k - 1]); } else { /* backward tranform: w -> conjugate(w) */ w1_real = GSL_REAL(twiddle1[k - 1]); w1_imag = -GSL_IMAG(twiddle1[k - 1]); w2_real = GSL_REAL(twiddle2[k - 1]); w2_imag = -GSL_IMAG(twiddle2[k - 1]); w3_real = GSL_REAL(twiddle3[k - 1]); w3_imag = -GSL_IMAG(twiddle3[k - 1]); w4_real = GSL_REAL(twiddle4[k - 1]); w4_imag = -GSL_IMAG(twiddle4[k - 1]); w5_real = GSL_REAL(twiddle5[k - 1]); w5_imag = -GSL_IMAG(twiddle5[k - 1]); } } for (k1 = 0; k1 < p_1; k1++) { const ATOMIC z0_real = REAL(in,istride,i); const ATOMIC z0_imag = IMAG(in,istride,i); const ATOMIC z1_real = REAL(in,istride,i+m); const ATOMIC z1_imag = IMAG(in,istride,i+m); const ATOMIC z2_real = REAL(in,istride,i+2*m); const ATOMIC z2_imag = IMAG(in,istride,i+2*m); const ATOMIC z3_real = REAL(in,istride,i+3*m); const ATOMIC z3_imag = IMAG(in,istride,i+3*m); const ATOMIC z4_real = REAL(in,istride,i+4*m); const ATOMIC z4_imag = IMAG(in,istride,i+4*m); const ATOMIC z5_real = REAL(in,istride,i+5*m); const ATOMIC z5_imag = IMAG(in,istride,i+5*m); /* compute x = W(6) z */ /* W(6) is a combination of sums and differences of W(3) acting on the even and odd elements of z */ /* ta1 = z2 + z4 */ const ATOMIC ta1_real = z2_real + z4_real; const ATOMIC ta1_imag = z2_imag + z4_imag; /* ta2 = z0 - ta1/2 */ const ATOMIC ta2_real = z0_real - ta1_real / 2; const ATOMIC ta2_imag = z0_imag - ta1_imag / 2; /* ta3 = (+/-) sin(pi/3)*(z2 - z4) */ const ATOMIC ta3_real = ((int) sign) * tau * (z2_real - z4_real); const ATOMIC ta3_imag = ((int) sign) * tau * (z2_imag - z4_imag); /* a0 = z0 + ta1 */ const ATOMIC a0_real = z0_real + ta1_real; const ATOMIC a0_imag = z0_imag + ta1_imag; /* a1 = ta2 + i ta3 */ const ATOMIC a1_real = ta2_real - ta3_imag; const ATOMIC a1_imag = ta2_imag + ta3_real; /* a2 = ta2 - i ta3 */ const ATOMIC a2_real = ta2_real + ta3_imag; const ATOMIC a2_imag = ta2_imag - ta3_real; /* tb1 = z5 + z1 */ const ATOMIC tb1_real = z5_real + z1_real; const ATOMIC tb1_imag = z5_imag + z1_imag; /* tb2 = z3 - tb1/2 */ const ATOMIC tb2_real = z3_real - tb1_real / 2; const ATOMIC tb2_imag = z3_imag - tb1_imag / 2; /* tb3 = (+/-) sin(pi/3)*(z5 - z1) */ const ATOMIC tb3_real = ((int) sign) * tau * (z5_real - z1_real); const ATOMIC tb3_imag = ((int) sign) * tau * (z5_imag - z1_imag); /* b0 = z3 + tb1 */ const ATOMIC b0_real = z3_real + tb1_real; const ATOMIC b0_imag = z3_imag + tb1_imag; /* b1 = tb2 + i tb3 */ const ATOMIC b1_real = tb2_real - tb3_imag; const ATOMIC b1_imag = tb2_imag + tb3_real; /* b2 = tb2 - i tb3 */ const ATOMIC b2_real = tb2_real + tb3_imag; const ATOMIC b2_imag = tb2_imag - tb3_real; /* x0 = a0 + b0 */ const ATOMIC x0_real = a0_real + b0_real; const ATOMIC x0_imag = a0_imag + b0_imag; /* x4 = a1 + b1 */ const ATOMIC x4_real = a1_real + b1_real; const ATOMIC x4_imag = a1_imag + b1_imag; /* x2 = a2 + b2 */ const ATOMIC x2_real = a2_real + b2_real; const ATOMIC x2_imag = a2_imag + b2_imag; /* x3 = a0 - b0 */ const ATOMIC x3_real = a0_real - b0_real; const ATOMIC x3_imag = a0_imag - b0_imag; /* x1 = a1 - b1 */ const ATOMIC x1_real = a1_real - b1_real; const ATOMIC x1_imag = a1_imag - b1_imag; /* x5 = a2 - b2 */ const ATOMIC x5_real = a2_real - b2_real; const ATOMIC x5_imag = a2_imag - b2_imag; /* apply twiddle factors */ /* to0 = 1 * x0 */ REAL(out,ostride,j) = x0_real; IMAG(out,ostride,j) = x0_imag; /* to1 = w1 * x1 */ REAL(out,ostride,j+p_1) = w1_real * x1_real - w1_imag * x1_imag; IMAG(out,ostride,j+p_1) = w1_real * x1_imag + w1_imag * x1_real; /* to2 = w2 * x2 */ REAL(out,ostride,j+2*p_1) = w2_real * x2_real - w2_imag * x2_imag; IMAG(out,ostride,j+2*p_1) = w2_real * x2_imag + w2_imag * x2_real; /* to3 = w3 * x3 */ REAL(out,ostride,j+3*p_1) = w3_real * x3_real - w3_imag * x3_imag; IMAG(out,ostride,j+3*p_1) = w3_real * x3_imag + w3_imag * x3_real; /* to4 = w4 * x4 */ REAL(out,ostride,j+4*p_1) = w4_real * x4_real - w4_imag * x4_imag; IMAG(out,ostride,j+4*p_1) = w4_real * x4_imag + w4_imag * x4_real; /* to5 = w5 * x5 */ REAL(out,ostride,j+5*p_1) = w5_real * x5_real - w5_imag * x5_imag; IMAG(out,ostride,j+5*p_1) = w5_real * x5_imag + w5_imag * x5_real; i++; j++; } j += jump; } return 0; } drc-3.2.2/source/gsl/real_pass_3.c0000644000076400001450000001332312616157443015710 0ustar denisitadm/* fft/real_pass_3.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ static void FUNCTION(fft_real,pass_3) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[]) { size_t k, k1; const size_t factor = 3; const size_t m = n / factor; const size_t q = n / product; const size_t product_1 = product / factor; const ATOMIC tau = sqrt (3.0) / 2.0; for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC t1 = z1_real + z2_real; const ATOMIC x0_real = z0_real + t1; const ATOMIC x1_real = z0_real - t1 / 2.0; const ATOMIC x1_imag = -tau * (z1_real - z2_real); const size_t to0 = product * k1; const size_t to1 = to0 + 2 * product_1 - 1; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to1 + 1) = x1_imag; } if (product_1 == 1) return; for (k = 1; k < (product_1 + 1) / 2; k++) { const ATOMIC w1_real = GSL_REAL(twiddle1[k - 1]); const ATOMIC w1_imag = -GSL_IMAG(twiddle1[k - 1]); const ATOMIC w2_real = GSL_REAL(twiddle2[k - 1]); const ATOMIC w2_imag = -GSL_IMAG(twiddle2[k - 1]); for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + 2 * k - 1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const ATOMIC f0_real = VECTOR(in,istride,from0); const ATOMIC f0_imag = VECTOR(in,istride,from0 + 1); const ATOMIC f1_real = VECTOR(in,istride,from1); const ATOMIC f1_imag = VECTOR(in,istride,from1 + 1); const ATOMIC f2_real = VECTOR(in,istride,from2); const ATOMIC f2_imag = VECTOR(in,istride,from2 + 1); const ATOMIC z0_real = f0_real; const ATOMIC z0_imag = f0_imag; const ATOMIC z1_real = w1_real * f1_real - w1_imag * f1_imag; const ATOMIC z1_imag = w1_real * f1_imag + w1_imag * f1_real; const ATOMIC z2_real = w2_real * f2_real - w2_imag * f2_imag; const ATOMIC z2_imag = w2_real * f2_imag + w2_imag * f2_real; /* compute x = W(3) z */ /* t1 = z1 + z2 */ const ATOMIC t1_real = z1_real + z2_real; const ATOMIC t1_imag = z1_imag + z2_imag; /* t2 = z0 - t1/2 */ const ATOMIC t2_real = z0_real - t1_real / 2; const ATOMIC t2_imag = z0_imag - t1_imag / 2; /* t3 = (+/-) sin(pi/3)*(z1 - z2) */ const ATOMIC t3_real = -tau * (z1_real - z2_real); const ATOMIC t3_imag = -tau * (z1_imag - z2_imag); /* x0 = z0 + t1 */ const ATOMIC x0_real = z0_real + t1_real; const ATOMIC x0_imag = z0_imag + t1_imag; /* x1 = t2 + i t3 */ const ATOMIC x1_real = t2_real - t3_imag; const ATOMIC x1_imag = t2_imag + t3_real; /* x2 = t2 - i t3 */ const ATOMIC x2_real = t2_real + t3_imag; const ATOMIC x2_imag = t2_imag - t3_real; /* apply twiddle factors */ const size_t to0 = k1 * product + 2 * k - 1; const size_t to1 = to0 + 2 * product_1; const size_t to2 = 2 * product_1 - 2 * k + k1 * product - 1; /* to0 = 1 * x0 */ VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; /* to1 = 1 * x1 */ VECTOR(out,ostride,to1) = x1_real; VECTOR(out,ostride,to1 + 1) = x1_imag; /* to2 = 1 * x2 */ VECTOR(out,ostride,to2) = x2_real; VECTOR(out,ostride,to2 + 1) = -x2_imag; } } if (product_1 % 2 == 1) return; for (k1 = 0; k1 < q; k1++) { const size_t from0 = k1 * product_1 + product_1 - 1; const size_t from1 = from0 + m; const size_t from2 = from1 + m; const ATOMIC z0_real = VECTOR(in,istride,from0); const ATOMIC z1_real = VECTOR(in,istride,from1); const ATOMIC z2_real = VECTOR(in,istride,from2); const ATOMIC t1 = z1_real - z2_real; const ATOMIC x0_real = z0_real + t1 / 2.0; const ATOMIC x0_imag = -tau * (z1_real + z2_real); const ATOMIC x1_real = z0_real - t1; const size_t to0 = k1 * product + product_1 - 1; const size_t to1 = to0 + 2 * product_1; VECTOR(out,ostride,to0) = x0_real; VECTOR(out,ostride,to0 + 1) = x0_imag; VECTOR(out,ostride,to1) = x1_real; } return; } drc-3.2.2/source/gsl/real_init.c0000644000076400001450000001047412616157443015467 0ustar denisitadm/* fft/real_init.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007, 2009 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ TYPE(gsl_fft_real_wavetable) * FUNCTION(gsl_fft_real_wavetable,alloc) (size_t n) { int status; size_t i; size_t n_factors; size_t t, product, product_1, q; double d_theta; TYPE(gsl_fft_real_wavetable) * wavetable; if (n == 0) { GSL_ERROR_VAL ("length n must be positive integer", GSL_EDOM, 0); } wavetable = (TYPE(gsl_fft_real_wavetable) *) malloc(sizeof(TYPE(gsl_fft_real_wavetable))); if (wavetable == NULL) { GSL_ERROR_VAL ("failed to allocate struct", GSL_ENOMEM, 0); } if (n == 1) { wavetable->trig = 0; } else { wavetable->trig = (TYPE(gsl_complex) *) malloc ((n / 2) * sizeof (TYPE(gsl_complex))); if (wavetable->trig == NULL) { /* error in constructor, prevent memory leak */ free(wavetable) ; GSL_ERROR_VAL ("failed to allocate trigonometric lookup table", GSL_ENOMEM, 0); } } wavetable->n = n; status = fft_real_factorize (n, &n_factors, wavetable->factor); if (status) { /* error in constructor, prevent memory leak */ free(wavetable->trig); free(wavetable) ; GSL_ERROR_VAL ("factorization failed", GSL_EFACTOR, 0); } wavetable->nf = n_factors; d_theta = 2.0 * M_PI / ((double) n); t = 0; product = 1; for (i = 0; i < wavetable->nf; i++) { size_t j; const size_t factor = wavetable->factor[i]; wavetable->twiddle[i] = wavetable->trig + t; product_1 = product; /* product_1 = p_(i-1) */ product *= factor; q = n / product; for (j = 1; j < factor; j++) { size_t k; size_t m = 0; for (k = 1; k < (product_1 + 1) / 2; k++) { double theta; m = m + j * q; m = m % n; theta = d_theta * m; /* d_theta*j*k*q */ GSL_REAL(wavetable->trig[t]) = cos (theta); GSL_IMAG(wavetable->trig[t]) = sin (theta); t++; } } } if (t > (n / 2)) { /* error in constructor, prevent memory leak */ free(wavetable->trig); free(wavetable) ; GSL_ERROR_VAL ("overflowed trigonometric lookup table", GSL_ESANITY, 0); } return wavetable; } TYPE(gsl_fft_real_workspace) * FUNCTION(gsl_fft_real_workspace,alloc) (size_t n) { TYPE(gsl_fft_real_workspace) * workspace; if (n == 0) { GSL_ERROR_VAL ("length n must be positive integer", GSL_EDOM, 0); } workspace = (TYPE(gsl_fft_real_workspace) *) malloc(sizeof(TYPE(gsl_fft_real_workspace))); if (workspace == NULL) { GSL_ERROR_VAL ("failed to allocate struct", GSL_ENOMEM, 0); } workspace->n = n; workspace->scratch = (BASE *) malloc (n * sizeof (BASE)); if (workspace->scratch == NULL) { /* error in constructor, prevent memory leak */ free(workspace) ; GSL_ERROR_VAL ("failed to allocate scratch space", GSL_ENOMEM, 0); } return workspace; } void FUNCTION(gsl_fft_real_wavetable,free) (TYPE(gsl_fft_real_wavetable) * wavetable) { RETURN_IF_NULL (wavetable); /* release trigonometric lookup tables */ free (wavetable->trig); wavetable->trig = NULL; free (wavetable) ; } void FUNCTION(gsl_fft_real_workspace,free) (TYPE(gsl_fft_real_workspace) * workspace) { RETURN_IF_NULL (workspace); /* release scratch space */ free (workspace->scratch); workspace->scratch = NULL; free (workspace) ; } drc-3.2.2/source/gsl/gsl_types.h0000644000076400001450000000217512616157443015536 0ustar denisitadm/* gsl_types.h * * Copyright (C) 2001, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __GSL_TYPES_H__ #define __GSL_TYPES_H__ #ifndef GSL_VAR #ifdef WIN32 # ifdef GSL_DLL # ifdef DLL_EXPORT # define GSL_VAR extern __declspec(dllexport) # else # define GSL_VAR extern __declspec(dllimport) # endif # else # define GSL_VAR extern # endif #else # define GSL_VAR extern #endif #endif #endif /* __GSL_TYPES_H__ */ drc-3.2.2/source/gsl/hc_pass.h0000644000076400001450000000636512616157443015152 0ustar denisitadm/* fft/hc_pass.h * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "complex_internal.h" static void FUNCTION(fft_halfcomplex,pass_2) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]); static void FUNCTION(fft_halfcomplex,pass_3) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[]); static void FUNCTION(fft_halfcomplex,pass_4) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[]); static void FUNCTION(fft_halfcomplex,pass_5) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle1[], const TYPE(gsl_complex) twiddle2[], const TYPE(gsl_complex) twiddle3[], const TYPE(gsl_complex) twiddle4[]); static void FUNCTION(fft_halfcomplex,pass_n) (const BASE in[], const size_t istride, BASE out[], const size_t ostride, const size_t factor, const size_t product, const size_t n, const TYPE(gsl_complex) twiddle[]); drc-3.2.2/source/gsl/c_main.c0000644000076400001450000001573112616157443014750 0ustar denisitadm/* fft/c_main.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "c_pass.h" int FUNCTION(gsl_fft_complex,forward) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n, const TYPE(gsl_fft_complex_wavetable) * wavetable, TYPE(gsl_fft_complex_workspace) * work) { gsl_fft_direction sign = gsl_fft_forward; int status = FUNCTION(gsl_fft_complex,transform) (data, stride, n, wavetable, work, sign); return status; } int FUNCTION(gsl_fft_complex,backward) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n, const TYPE(gsl_fft_complex_wavetable) * wavetable, TYPE(gsl_fft_complex_workspace) * work) { gsl_fft_direction sign = gsl_fft_backward; int status = FUNCTION(gsl_fft_complex,transform) (data, stride, n, wavetable, work, sign); return status; } int FUNCTION(gsl_fft_complex,inverse) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n, const TYPE(gsl_fft_complex_wavetable) * wavetable, TYPE(gsl_fft_complex_workspace) * work) { gsl_fft_direction sign = gsl_fft_backward; int status = FUNCTION(gsl_fft_complex,transform) (data, stride, n, wavetable, work, sign); if (status) { return status; } /* normalize inverse fft with 1/n */ { const ATOMIC norm = ONE / (ATOMIC)n; size_t i; for (i = 0; i < n; i++) { REAL(data,stride,i) *= norm; IMAG(data,stride,i) *= norm; } } return status; } int FUNCTION(gsl_fft_complex,transform) (TYPE(gsl_complex_packed_array) data, const size_t stride, const size_t n, const TYPE(gsl_fft_complex_wavetable) * wavetable, TYPE(gsl_fft_complex_workspace) * work, const gsl_fft_direction sign) { const size_t nf = wavetable->nf; size_t i; size_t q, product = 1; TYPE(gsl_complex) *twiddle1, *twiddle2, *twiddle3, *twiddle4, *twiddle5, *twiddle6; size_t state = 0; BASE * const scratch = work->scratch; BASE * in = data; size_t istride = stride; BASE * out = scratch; size_t ostride = 1; if (n == 0) { GSL_ERROR ("length n must be positive integer", GSL_EDOM); } if (n == 1) { /* FFT of 1 data point is the identity */ return 0; } if (n != wavetable->n) { GSL_ERROR ("wavetable does not match length of data", GSL_EINVAL); } if (n != work->n) { GSL_ERROR ("workspace does not match length of data", GSL_EINVAL); } for (i = 0; i < nf; i++) { const size_t factor = wavetable->factor[i]; product *= factor; q = n / product; if (state == 0) { in = data; istride = stride; out = scratch; ostride = 1; state = 1; } else { in = scratch; istride = 1; out = data; ostride = stride; state = 0; } if (factor == 2) { twiddle1 = wavetable->twiddle[i]; FUNCTION(fft_complex,pass_2) (in, istride, out, ostride, sign, product, n, twiddle1); } else if (factor == 3) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + q; FUNCTION(fft_complex,pass_3) (in, istride, out, ostride, sign, product, n, twiddle1, twiddle2); } else if (factor == 4) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + q; twiddle3 = twiddle2 + q; FUNCTION(fft_complex,pass_4) (in, istride, out, ostride, sign, product, n, twiddle1, twiddle2, twiddle3); } else if (factor == 5) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + q; twiddle3 = twiddle2 + q; twiddle4 = twiddle3 + q; FUNCTION(fft_complex,pass_5) (in, istride, out, ostride, sign, product, n, twiddle1, twiddle2, twiddle3, twiddle4); } else if (factor == 6) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + q; twiddle3 = twiddle2 + q; twiddle4 = twiddle3 + q; twiddle5 = twiddle4 + q; FUNCTION(fft_complex,pass_6) (in, istride, out, ostride, sign, product, n, twiddle1, twiddle2, twiddle3, twiddle4, twiddle5); } else if (factor == 7) { twiddle1 = wavetable->twiddle[i]; twiddle2 = twiddle1 + q; twiddle3 = twiddle2 + q; twiddle4 = twiddle3 + q; twiddle5 = twiddle4 + q; twiddle6 = twiddle5 + q; FUNCTION(fft_complex,pass_7) (in, istride, out, ostride, sign, product, n, twiddle1, twiddle2, twiddle3, twiddle4, twiddle5, twiddle6); } else { twiddle1 = wavetable->twiddle[i]; FUNCTION(fft_complex,pass_n) (in, istride, out, ostride, sign, factor, product, n, twiddle1); } } if (state == 1) /* copy results back from scratch to data */ { for (i = 0; i < n; i++) { REAL(data,stride,i) = REAL(scratch,1,i) ; IMAG(data,stride,i) = IMAG(scratch,1,i) ; } } return 0; } drc-3.2.2/source/gsl/hc_init.c0000644000076400001450000000640612616157443015136 0ustar denisitadm/* fft/hc_init.c * * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007, 2009 Brian Gough * * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ TYPE(gsl_fft_halfcomplex_wavetable) * FUNCTION(gsl_fft_halfcomplex_wavetable,alloc) (size_t n) { int status; size_t i; size_t n_factors; size_t t, product, product_1, q; double d_theta; TYPE(gsl_fft_halfcomplex_wavetable) * wavetable ; if (n == 0) { GSL_ERROR_VAL ("length n must be positive integer", GSL_EDOM, 0); } wavetable = (TYPE(gsl_fft_halfcomplex_wavetable) *) malloc(sizeof(TYPE(gsl_fft_halfcomplex_wavetable))); if (wavetable == NULL) { GSL_ERROR_VAL ("failed to allocate struct", GSL_ENOMEM, 0); } wavetable->trig = (TYPE(gsl_complex) *) malloc (n * sizeof (TYPE(gsl_complex))); if (wavetable->trig == NULL) { /* error in constructor, prevent memory leak */ free(wavetable) ; GSL_ERROR_VAL ("failed to allocate trigonometric lookup table", GSL_ENOMEM, 0); } wavetable->n = n ; status = fft_halfcomplex_factorize (n, &n_factors, wavetable->factor); if (status) { /* error in constructor, prevent memory leak */ free(wavetable->trig) ; free(wavetable) ; GSL_ERROR_VAL ("factorization failed", GSL_EFACTOR, 0); } wavetable->nf = n_factors; d_theta = 2.0 * M_PI / ((double) n); t = 0; product = 1; for (i = 0; i < n_factors; i++) { size_t j; const size_t factor = wavetable->factor[i]; wavetable->twiddle[i] = wavetable->trig + t; product_1 = product; /* product_1 = p_(i-1) */ product *= factor; q = n / product; for (j = 1; j < factor; j++) { size_t k; size_t m = 0; for (k = 1; k < (q + 1) / 2; k++) { double theta; m = m + j * product_1; m = m % n; theta = d_theta * m; /* d_theta*j*k*product_1 */ GSL_REAL(wavetable->trig[t]) = cos (theta); GSL_IMAG(wavetable->trig[t]) = sin (theta); t++; } } } if (t > (n / 2)) { /* error in constructor, prevent memory leak */ free(wavetable->trig) ; free(wavetable) ; GSL_ERROR_VAL ("overflowed trigonometric lookup table", GSL_ESANITY, 0); } return wavetable; } void FUNCTION(gsl_fft_halfcomplex_wavetable,free) (TYPE(gsl_fft_halfcomplex_wavetable) * wavetable) { RETURN_IF_NULL (wavetable); /* release trigonometric lookup tables */ free (wavetable->trig); wavetable->trig = NULL; free (wavetable); } drc-3.2.2/source/psychoacoustic.cpp0000644000076400001450000003646013162156312016326 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002, 2008 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@neomerica.it ****************************************************************************/ /* Procedure a carattere psicoacustico e relative funzioni di supporto */ /* Inclusioni */ #include "psychoacoustic.h" #include "fft.h" #include "hd.h" #include "baselib.h" #include "dspwind.h" /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Ritorna l'ampiezza di banda a frazioni di ottava per una data frequenza */ DLReal FOctBWidth(const DLReal F,const DLReal FOW) { DLReal BW; BW = (DLReal) pow(2.0,FOW/2.0); return F * ((BW * BW) - 1) / BW; } /* Versione della funzione precedente che opera su un array di frequenze */ void AFOctBWidth(const DLReal * F, const int N,const DLReal FOW,DLReal * BW) { DLReal B1; int I; B1 = (DLReal) pow(2.0,FOW/2.0); B1 = ((B1 * B1) - 1) / B1; for (I = 0;I < N;I ++) BW[I] = F[I] * B1; } /* Ritorna l'ampiezza di banda per una data frequenza secondo la scala di Bark */ DLReal BarkBWidth(const DLReal F) { return (DLReal) (94 + 71 * (pow(F / 1000,1.5))); } /* Versione della funzione precedente che opera su un array di frequenze */ void ABarkBWidth(const DLReal * F, const int N,DLReal * BW) { int I; for (I = 0;I < N;I ++) BW[I] = (DLReal) (94 + 71 * (pow(F[I] / 1000,1.5))); } /* Ritorna l'ampiezza di banda per una data frequenza secondo la scala ERB */ DLReal ERBBWidth(const DLReal F) { return ((DLReal) 0.108) * F + ((DLReal) 24.7); } /* Versione della funzione precedente che opera su un array di frequenze */ void AERBBWidth(const DLReal * F, const int N,DLReal * BW) { int I; for (I = 0;I < N;I ++) BW[I] = ((DLReal) 0.108) * F[I] + ((DLReal) 24.7); } /* Calcola la somma cumnulativa sull'array A. Se l'array S non null la somma cumulativa viene posta nell'array S, altrimenti viene posta direttamente in A sostituendo i valori contenuti */ void CumulativeSum(DLReal * A,const int N,DLReal * S) { DLReal * CS; DLReal CV; DLReal SC; DLReal SY; DLReal ST; int I; if (S == NULL) CS = A; else CS = S; /* Kahan summation algorithm */ CV = (DLReal) 0.0; SC = (DLReal) 0.0; for (I = 0;I < N;I ++) { SY = A[I] - SC; ST = CV + SY; SC = (ST - CV) - SY; CS[I] = CV = ST; } } /* Tipo per le elaborazioni interne dell'inviluppo spettrale */ /* Il calcolo dell'inviluppo spettrale richiede una elevata precisione in particolare nel caso in cui il fattore di approssimazione dei picchi sia molto elevato (> 30) */ typedef long double SEFloat; /* Somma cumulativa per l'inviluppo spettrale */ static void SECumulativeSum(SEFloat * A,const int N,SEFloat * S) { SEFloat * CS; SEFloat CV; SEFloat SC; SEFloat SY; SEFloat ST; int I; if (S == NULL) CS = A; else CS = S; /* Kahan summation algorithm */ CV = (SEFloat) 0.0; SC = (SEFloat) 0.0; for (I = 0;I < N;I ++) { SY = A[I] - SC; ST = CV + SY; SC = (ST - CV) - SY; CS[I] = CV = ST; } } /* Funzione per il calcolo dell'esponenziale nella procedura di estrazione dell'inviluppo spettrale */ #define SEPow(x,y) powl(x,y) /* Calcola l'inviluppo spettrale del segnale S con approssimazione dei picchi PDS e risoluzione BW, espressa in frazioni di ottava. Nel caso in cui PDS sia pari a 1.0 esegue il classico smoothing a frazioni di ottava. Nel caso in cui BW sia minore di 0.0 usa la scala di Bark, nel caso in cui BW sia minore di -1.0 usa la scala ERB */ Boolean SpectralEnvelope(const DLReal * S,const int N,const int FS, const DLReal BW,const DLReal PDS,DLReal * SE) { DLComplex * CSP; SEFloat * SP; SEFloat * TSP; SEFloat NF; DLReal BWF; int I; int J; int * BU; int * BL; /* Alloca l'array per l'estrazione dello spettro */ if ((CSP = new DLComplex[2 * N]) == NULL) return False; /* Effettua il padding del segnale */ for (I = 0;I < N;I++) CSP[I] = S[I]; for (I = N;I < 2 * N;I++) CSP[I] = (DLReal) 0.0; /* Calcola lo spettro del asegnale */ if (Fft(CSP,2 * N) == False) { delete[] CSP; return False; } /* Alloca l'array per l'estrazione dell'inviluppo */ if ((SP = new SEFloat[N + 1]) == NULL) { delete[] CSP; return False; } /* Estrae l'ampiezza del segnale */ SP[0] = (SEFloat) 0.0; for (I = 0,J = 1;I < N;I++,J++) SP[J] = std::abs(CSP[I]); /* Normalizza l'ampiezza */ NF = (SEFloat) 0.0; for (I = 0;I < N + 1;I++) { if (SP[I] > NF) NF = SP[I]; } if (NF > (SEFloat) 0.0) { for (I = 0;I < N + 1;I++) SP[I] /= NF; } /* Dealloca l'array per l'estrazione dello spettro */ delete[] CSP; /* Alloca gli array per gli intervalli estrazione inviluppo */ if ((BU = new int[N]) == NULL) { delete[] SP; return False; } if ((BL = new int[N]) == NULL) { delete[] BU; delete[] SP; return False; } /* Calcola gli intervalli calcolo inviluppo */ if (BW >= ((DLReal) 0.0)) { /* Risoluzione a frazioni di ottava */ BWF = (DLReal) pow(2.0,BW / 2.0); /* Calcolo intervalli */ for (I = 0;I < N;I++) { BU[I] = (int) floor(1.5 + (I * BWF)); if (BU[I] > N) BU[I] = N; BL[I] = (int) floor(0.5 + (I / BWF)); } } else if (BW >= ((DLReal) -1.0)) { /* Scala di Bark */ for (I = 0;I < N;I++) SE[I] = (((DLReal) 0.5) * I * FS) / (N - 1); ABarkBWidth(SE,N,SE); /* Imposta il primo punto */ BL[0] = 0; BU[0] = 1; /* Calcolo intervalli */ for (I = 1;I < N;I++) { BWF = (((DLReal) 0.5) * I * FS) / (N - 1); BWF = (DLReal) ((sqrt(SE[I] * SE[I] + 4 * BWF * BWF) + SE[I]) / (2 * BWF)); BU[I] = (int) floor(1.5 + (I * BWF)); if (BU[I] > N) BU[I] = N; BL[I] = (int) floor(0.5 + (I / BWF)); } } else { /* Scala ERB */ for (I = 0;I < N;I++) SE[I] = (((DLReal) 0.5) * I * FS) / (N - 1); AERBBWidth(SE,N,SE); /* Imposta il primo punto */ BL[0] = 0; BU[0] = 1; /* Calcolo intervalli */ for (I = 1;I < N;I++) { BWF = (((DLReal) 0.5) * I * FS) / (N - 1); BWF = (DLReal) ((sqrt(SE[I] * SE[I] + 4 * BWF * BWF) + SE[I]) / (2 * BWF)); BU[I] = (int) floor(1.5 + (I * BWF)); if (BU[I] > N) BU[I] = N; BL[I] = (int) floor(0.5 + (I / BWF)); } } /* Alloca l'array di supporto per l'estrazione dell'inviluppo */ if ((TSP = new SEFloat[N + 1]) == NULL) { delete[] BU; delete[] BL; delete[] SP; return False; } /* Verifica se abilitata l'approssimazione dei picchi */ if (PDS <= (DLReal) 1.0) { /* Smoothing tradizionale */ SECumulativeSum(SP,N + 1,NULL); TSP[0] = (SEFloat) 0.0; for (I = 0,J = 1;I < N;I++,J++) TSP[J] = (SP[BU[I]] - SP[BL[I]]) / (BU[I] - BL[I]); } else { /* Smoothing con approssimazione picchi */ for (I = 0;I < N + 1;I++) SP[I] = (SEFloat) SEPow(SP[I],PDS); SECumulativeSum(SP,N + 1,NULL); BWF = ((DLReal) 1.0) / PDS; TSP[0] = (SEFloat) 0.0; for (I = 0,J = 1;I < N;I++,J++) TSP[J] = (SEFloat) SEPow((SP[BU[I]] - SP[BL[I]]) / (BU[I] - BL[I]),BWF); /* Interpolazione picchi */ SECumulativeSum(TSP,N + 1,NULL); SP[0] = (SEFloat) 0.0; for (I = 0,J = 1;I < N;I++,J++) SP[J] = (TSP[BU[I]] - TSP[BL[I]]) / (BU[I] - BL[I]); for (I = 0;I < N + 1;I++) TSP[I] = SP[I]; } /* Smoothing finale */ SECumulativeSum(TSP,N + 1,NULL); for (I = 0;I < N;I++) SE[I] = (DLReal) (NF * ((TSP[BU[I]] - TSP[BL[I]]) / (BU[I] - BL[I]))); /* Dealloca gli array temporanei */ delete[] BL; delete[] BU; delete[] TSP; delete[] SP; /* Operazione completata */ return True; } /* Calola il valore RMS dell'inviluppo spettrale sulla banda di frequenze indicate */ static DLReal SEGetBLFFTRMSLevel(const DLReal * SEArray,const int SESize,const int SampleFreq, const DLReal StartFreq,const DLReal EndFreq) { DLReal RMS; int I; int FS; int FE; /* Determina gli indici per il calcolo del valore RMS */ FS = (int) floor(((2 * SESize * StartFreq) / SampleFreq)); FE = (int) floor(((2 * SESize * EndFreq) / SampleFreq)); /* Calcola il livello RMS */ RMS = (DLReal) 0.0; for (I = FS;I < FE;I++) RMS += SEArray[I] * SEArray[I]; return (DLReal) sqrt(RMS / SESize); } /* Limitazione valli per inviluppo spettrale con calcolo del valore RMS sull banda indicata */ static void C1SEDipLimit(DLReal * SE,const int SESize,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq) { int I; DLReal RMSLevel; DLReal DLSLevel; DLReal DLLevel; DLReal DLGFactor; DLReal DLAbs; /* Determina il livello RMS del segnale */ RMSLevel = MinGain * SEGetBLFFTRMSLevel(SE,SESize,SampleFreq,StartFreq,EndFreq); /* Verifica il tipo di limitazione impostata */ if (DLStart >= (DLReal) 1.0) { /* Scansione per troncatura guadagno */ for (I = 0; I < SESize; I++) { DLAbs = SE[I]; if (DLAbs < RMSLevel) SE[I] = RMSLevel; } } else { /* Determina i fattori per la limitazione guadagno */ DLSLevel = RMSLevel / DLStart; DLGFactor = DLSLevel - RMSLevel; /* Scansione per limitazione guadagno */ for (I = 0; I < SESize; I++) { DLAbs = SE[I]; if (DLAbs < DLSLevel) { /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - DLAbs) / DLGFactor; DLLevel = DLLevel / (((DLReal) 1.0) + DLLevel); SE[I] = DLSLevel - DLGFactor * DLLevel; } } } } /* Calcola un filtro target basato sull'inviluppo spettrale. Il filtro ha lunghezza pari a 2 volte la lunghezza del segnale in ingresso e non finestrato */ Boolean MKSETargetFilter(const DLReal * S,const int N,const int FS, const DLReal BW,const DLReal PDS,DLReal * TF,const MKSETFType TFType, const DLReal MinGain,const DLReal DLStart,const int SampleFreq, const DLReal StartFreq,const DLReal EndFreq) { DLComplex * CSE; int I; int J; Boolean LogLimit; DLReal CV; /* Calcola l'inviluppo spettrale */ if (SpectralEnvelope(S,N,FS,BW,PDS,TF) == False) return False; /* Effettua la limitazione valli sull'inviluppo spettrale */ C1SEDipLimit(TF,N,MinGain,DLStart,SampleFreq,StartFreq,EndFreq); /* Alloca l'array per il calcolo del filtro target */ if ((CSE = new DLComplex[2 * N]) == NULL) return False; /* Verifica il tipo di filtro impostato */ switch (TFType) { /* Fase lineare */ case MKSETFLinearPhase: /* Imposta la risposta in ampiezza */ for (I = 0,J = (2 * N) - 1;I < N;I++,J--) CSE[J] = -(CSE[I] = ((DLReal) 1.0) / TF[I]); for (I = 0;I < 2 * N;I++) CSE[I] *= UnitRoot(I,4 * N); /* Calcola il filtro */ if (IFft(CSE,2 * N) == False) { delete[] CSE; return False; } /* Estrae il filtro a fase lineare */ for (I = 0,J = N;I < N;I++,J++) { TF[I] = std::real(CSE[N - (I + 1)]); TF[J] = std::real(CSE[I]); } /* Dealloca l'array per il calcolo filtro target */ delete[] CSE; break; /* Fase minima */ case MKSETFMinimumPhase: /* Calcola i valori per il cepstrum */ LogLimit = False; for (I = 0,J = (2 * N) - 1;I < N;I++,J--) { CV = TF[I]; if (CV <= (DLReal) 0.0) { LogLimit = True; CSE[I] = CSE[J] = (DLReal) -log(DRCMinFloat); } else CSE[I] = CSE[J] = -std::log(CV); } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: log limit reached in cepstrum computation."); /* Calcola il cepstrum */ IFft(CSE,2 * N); /* Finestra il cepstrum */ for (I = 1; I < N;I++) CSE[I] *= 2; for (I = N + 1; I < 2 * N;I++) CSE[I] = 0; /* Calcola la trsformata del cepstrum finestrato */ Fft(CSE,2 * N); /* Effettua il calcolo dell'esponenziale */ for (I = 0;I < 2 * N;I++) CSE[I] = std::exp(CSE[I]); /* Determina la risposta del sistema a fase minima */ IFft(CSE,2 * N); /* Copia il risultato nell'array destinazione */ for (I = 0;I < 2 * N;I++) TF[I] = std::real(CSE[I]); /* Dealloca l'array per il calcolo filtro target */ delete[] CSE; break; } /* Operazione completata */ return True; } /* Versione della funzione precedente che effettua un padding del segnale in ingresso alla prima potenza di due disponibile. Il filtro in uscita ha lunghezza pari a TFN. TFN non pu essere superiore alla lunghezza usata internamente per il calcolo del filtro, quindi 2 * N se MExp < 0, oppure 2 * nextpow2(N) * 2 ^ MExp per MExp >= 0 */ Boolean P2MKSETargetFilter(const DLReal * S,const int N,const int FS, const DLReal BW,const DLReal PDS,DLReal * TF,const MKSETFType TFType, const int MExp,const int TFN, const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq, const DLReal EndFreq) { DLReal * PS; DLReal * PTF; int I; int J; int PN; /* Controlla se si deve adottare una potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for (PN = 1;PN <= N;PN <<= 1); PN *= 1 << MExp; } else PN = N; /* Controlla che la lunghezza richiesta sia valida */ if (TFN > 2 * PN) return False; /* Alloca l'array per il padding del segnale */ if ((PS = new DLReal[PN]) == NULL) return False; /* Alloca l'array per il filtro target */ if ((PTF = new DLReal[2 * PN]) == NULL) { delete[] PS; return False; } /* Effettua il padding del segnale */ for (I = 0;I < N;I++) PS[I] = S[I]; for (I = N;I < PN;I++) PS[I] = (DLReal) 0.0; /* Calcola il filtro target */ if (MKSETargetFilter(PS,PN,FS,BW,PDS,PTF,TFType,MinGain,DLStart,SampleFreq,StartFreq,EndFreq) == False) { delete[] PS; delete[] PTF; return False; } /* Verifica il tipo di filtro impostato */ switch (TFType) { /* Fase lineare */ case MKSETFLinearPhase: /* Effettua la finestratura */ BlackmanWindow(&PTF[(2 * PN - TFN) / 2],TFN); /* Copia il filtro destinazione */ for (I = 0,J = (2 * PN - TFN) / 2;I < TFN;I++,J++) TF[I] = PTF[J]; break; /* Fase minima */ case MKSETFMinimumPhase: /* Effettua la finestratura */ HalfBlackmanWindow(PTF,TFN,0,WRight); /* Copia il filtro destinazione */ for (I = 0;I < TFN;I++) TF[I] = PTF[I]; break; } /* Dealloca gli array temporanei */ delete[] PS; delete[] PTF; /* Operazione completata */ return True; } drc-3.2.2/source/level.cpp0000644000076400001450000012426313165105152014373 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Funzioni correzione e gestione livello del segnale */ /* Inclusioni */ #include "level.h" #include "baselib.h" #include "fft.h" #include "dspwind.h" #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Calola il valore RMS del segnale Sig */ DLReal GetRMSLevel(const DLReal * Sig,const int SigLen) { DLReal RMS; int I; /* Variabili di supporto per il Kahan summation algorithm */ DLReal KC; DLReal KY; DLReal KT; /* Calcolo RMS */ RMS = (DLReal) 0.0; KC = (DLReal) 0.0; for (I = 0; I < SigLen; I++) { KY = (Sig[I] * Sig[I]) - KC; KT = RMS + KY; KC = (KT - RMS) - KY; RMS = KT; } /* Ritorna il valore normalizzato */ return (DLReal) sqrt(RMS); } /* Calola il valore RMS del segnale Sig sulla banda di frequenze indicate con pesatura in frequenza pari a 1/(f^w). Per W = 0 calcola il normale valore RMS, per W = 1 assegna peso uguale in potenza per ottava/decade. */ DLReal GetBLRMSLevel(const DLReal * Sig,const int SigLen,const int SampleFreq, const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { DLReal RMS; int I; DLComplex * FFTArray; int FFTSize; /* Determina la prima potenza di 2 >= SigLen */ if (MExp >= 0) { /* Determina la prima potenza di 2 >= SigLen */ for(FFTSize = 1;FFTSize <= SigLen;FFTSize <<= 1); FFTSize *= 1 << MExp; } else FFTSize = SigLen; /* Alloca l'array per l'fft */ FFTArray = new DLComplex[FFTSize]; if (FFTArray == NULL) return False; /* Copia il segnale nell'array */ for (I = 0;I < SigLen;I++) FFTArray[I] = Sig[I]; for (I = SigLen;I < FFTSize;I++) FFTArray[I] = (DLReal) 0.0; /* Effettua l'fft del segnale */ Fft(FFTArray,FFTSize); /* Calcola il valore RMS sulla banda interessata */ RMS = GetBLFFTRMSLevel(FFTArray,FFTSize,SampleFreq,StartFreq,EndFreq,W); /* Dealloca l'array FFT */ delete[] FFTArray; /* Ritorna il valore RMS */ return RMS; } /* EulerMascheroni constant */ #define RMSEMC (0.57721566490153286060651209008240243104215933593992) /* Limite calcolo diretto */ #define RMSHNL (256) /* Calola il valore RMS del segnale trasformato FFTArray sulla banda di frequenze indicate con pesatura in frequenza pari a 1/(f^w). Per W = 0 calcola il normale valore RMS, per W = 1 assegna peso uguale in potenza per ottava/decade. */ DLReal GetBLFFTRMSLevel(const DLComplex * FFTArray,const int FFTSize,const int SampleFreq, const DLReal StartFreq,const DLReal EndFreq,const DLReal W) { DLReal RMS; int I; int FS; int FE; int HS; /* Fattore di compensazione per pesatura */ DLReal CF; /* Variabili di supporto per il Kahan summation algorithm nel calcolo del fattore di compensazione */ DLReal KC; DLReal KY; DLReal KT; /* Determina gli indici per il calcolo del valore RMS */ FS = (int) floor(0.5 + ((FFTSize * StartFreq) / SampleFreq)); FE = (int) floor(0.5 + ((FFTSize * EndFreq) / SampleFreq)); HS = FFTSize / 2; /* Calcola il livello RMS */ if (W == ((DLReal) 0.0)) { /* Valore iniziale */ if (FS > 0) RMS = (DLReal) 0.0; else { RMS = std::real(FFTArray[0]) * std::real(FFTArray[0]); FS = 1; } /* Calcolo RMS */ KC = (DLReal) 0.0; for (I = FS;I < FE;I++) { KY = std::norm(FFTArray[I]) - KC; KT = RMS + KY; KC = (KT - RMS) - KY; RMS = KT; } return (DLReal) sqrt(2.0 * RMS / FFTSize); } else { /* Valore iniziale */ if (FS > 0) { /* Nessuna componente DC */ CF = (DLReal) 0.0; RMS = (DLReal) 0.0; } else { /* Assume che la componente DC abbia lo stesso peso della prima componente utile */ CF = (DLReal) 1.0; RMS = CF * std::real(FFTArray[0]) * std::real(FFTArray[0]); FS = 1; } /* Calcolo RMS */ KC = ((DLReal) 0.0); for (I = FS;I < FE;I++) { KY = (std::norm(FFTArray[I]) * ((DLReal) pow(I,-W))) - KC; KT = RMS + KY; KC = (KT - RMS) - KY; RMS = KT; } /* Calcola il fattore di normalizzazione, pari al numero armonico */ if (HS < RMSHNL) { /* Error > 1e-16, harmonic number direct computation */ KC = ((DLReal) 0.0); for (I = HS;I > 0;I--) { KY = ((DLReal) pow(I,-W)) - KC; KT = CF + KY; KC = (KT - CF) - KY; CF = KT; } } else { /* Error < 1e-16, harmonic number approximation */ CF += (DLReal) (RMSEMC + log(HS) + 1.0 / (2 * HS) - 1.0 / (12.0 * HS * HS) + 1.0 / (120.0 * pow(HS,4.0))); } return (DLReal) sqrt(RMS / CF); } } /* Effettua la normalizzazione del segnale al valore indicato e secondo il metodo indicato */ Boolean SigNormalize(DLReal * Sig,const int SigLen,const DLReal NormFactor, const NormType TNorm) { DLReal NormBase; int I; DLComplex * PFA; DLReal CAV; switch (TNorm) { case NormEuclidean: { NormBase = GetRMSLevel(Sig,SigLen); if (NormBase <= (DLReal) 0.0) return False; for (I = 0; I < SigLen; I++) Sig[I] = (Sig[I] * NormFactor) / NormBase; } break; case NormMax: { NormBase = (DLReal) 0.0; for (I = 0; I < SigLen; I++) if (((DLReal) fabs(Sig[I])) > NormBase) NormBase = (DLReal) fabs(Sig[I]); if (NormBase <= (DLReal) 0.0) return False; for (I = 0; I < SigLen; I++) Sig[I] = (Sig[I] * NormFactor) / NormBase; } break; case NormSum: { NormBase = (DLReal) 0.0; for (I = 0; I < SigLen; I++) NormBase += (DLReal) fabs(Sig[I]); if (NormBase <= (DLReal) 0.0) return False; for (I = 0; I < SigLen; I++) Sig[I] = (Sig[I] * NormFactor) / NormBase; } break; case NormFFTPeak: { if ((PFA = new DLComplex[SigLen]) == NULL) return False; for (I = 0; I < SigLen; I++) PFA[I] = Sig[I]; if (Fft(PFA,SigLen) == False) { delete[] PFA; return False; } NormBase = (DLReal) 0.0; for (I = 0; I < SigLen / 2; I++) { CAV = std::abs(PFA[I]); if (CAV > NormBase) NormBase = CAV; } if (NormBase <= (DLReal) 0.0) { delete[] PFA; return False; } for (I = 0; I < SigLen; I++) Sig[I] = (Sig[I] * NormFactor) / NormBase; delete[] PFA; } break; } /* Operazione completata */ return True; } /* Limitazione valli a fase lineare con calcolo del valore RMS sull banda indicata */ Boolean LPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { int FFTSize; int I; int J; DLComplex * FFTArray; DLReal RMSLevel; DLReal DLSLevel; DLReal DLLevel; DLReal DLGFactor; DLReal DLMFactor = 0; DLReal DLAbs; DLReal DLMin; /* Determina la prima potenza di 2 >= SigLen */ if (MExp >= 0) { /* Determina la prima potenza di 2 >= SigLen */ for (FFTSize = 1;FFTSize <= SigLen;FFTSize <<= 1); FFTSize *= 1 << MExp; } else FFTSize = SigLen; /* Alloca l'array per l'fft */ FFTArray = new DLComplex[FFTSize]; if (FFTArray == NULL) return False; /* Copia il segnale nell'array */ for (I = 0;I < SigLen;I++) FFTArray[I] = Sig[I]; for (I = SigLen;I < FFTSize;I++) FFTArray[I] = (DLReal) 0.0; /* Effettua l'fft del segnale */ Fft(FFTArray,FFTSize); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray,FFTSize,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello minimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MinGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (DLStart >= (DLReal) 1.0) { /* Scansione per troncatura guadagno */ for (I = 0; I < FFTSize; I++) { DLAbs = std::abs(FFTArray[I]); if (DLAbs < RMSLevel) FFTArray[I] = std::polar(RMSLevel,std::arg(FFTArray[I])); } } else { /* Determina i fattori per la limitazione guadagno */ DLSLevel = RMSLevel / DLStart; DLGFactor = DLSLevel - RMSLevel; DLMin = (DLReal) -1.0; /* Scansione per limitazione guadagno */ for (I = 0; I < FFTSize; I++) { DLAbs = std::abs(FFTArray[I]); if (DLAbs < DLSLevel) { /* Verifica se gi disponibile il minimo locale */ if (DLMin < (DLReal) 0.0) { /* Cerca il minimo locale */ DLMin = DLAbs; DLLevel = DLAbs; for (J = I + 1; J < FFTSize && DLLevel < DLSLevel; J++) { if (DLLevel < DLMin) DLMin = DLLevel; DLLevel = std::abs(FFTArray[J]); } /* Verifica se il minimo locale inferiore al livello minimo e ricalcola i fattori di compressione */ if (DLMin < RMSLevel) DLMFactor = DLSLevel - DLMin; else DLMFactor = DLSLevel - RMSLevel; } /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - DLAbs) / DLMFactor; FFTArray[I] = std::polar(DLSLevel - DLGFactor * DLLevel, std::arg(FFTArray[I])); } else DLMin = (DLReal) -1.0; } } /* Effettua l'fft inversa del segnale */ IFft(FFTArray,FFTSize); /* Ritorna il segnale limitato */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray[I]); /* Dealloca l'array */ delete[] FFTArray; /* Operazione completata */ return True; } /* Limitazione valli a fase lineare con calcolo del valore RMS sulla banda indicata */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1LPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { int FFTSize; int I; DLComplex * FFTArray; DLReal RMSLevel; DLReal DLSLevel; DLReal DLLevel; DLReal DLGFactor; DLReal DLAbs; /* Determina la prima potenza di 2 >= SigLen */ if (MExp >= 0) { /* Determina la prima potenza di 2 >= SigLen */ for (FFTSize = 1;FFTSize <= SigLen;FFTSize <<= 1); FFTSize *= 1 << MExp; } else FFTSize = SigLen; /* Alloca l'array per l'fft */ FFTArray = new DLComplex[FFTSize]; if (FFTArray == NULL) return False; /* Copia il segnale nell'array */ for (I = 0;I < SigLen;I++) FFTArray[I] = Sig[I]; for (I = SigLen;I < FFTSize;I++) FFTArray[I] = (DLReal) 0.0; /* Effettua l'fft del segnale */ Fft(FFTArray,FFTSize); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray,FFTSize,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello minimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MinGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (DLStart >= (DLReal) 1.0) { /* Scansione per troncatura guadagno */ for (I = 0; I < FFTSize; I++) { DLAbs = std::abs(FFTArray[I]); if (DLAbs < RMSLevel) FFTArray[I] = std::polar(RMSLevel,std::arg(FFTArray[I])); } } else { /* Determina i fattori per la limitazione guadagno */ DLSLevel = RMSLevel / DLStart; DLGFactor = DLSLevel - RMSLevel; /* Scansione per limitazione guadagno */ for (I = 0; I < FFTSize; I++) { DLAbs = std::abs(FFTArray[I]); if (DLAbs < DLSLevel) { /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - DLAbs) / DLGFactor; DLLevel = DLLevel / (((DLReal) 1.0) + DLLevel); FFTArray[I] = std::polar(DLSLevel - DLGFactor * DLLevel, std::arg(FFTArray[I])); } } } /* Effettua l'fft inversa del segnale */ IFft(FFTArray,FFTSize); /* Ritorna il segnale limitato */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray[I]); /* Dealloca l'array */ delete[] FFTArray; /* Operazione completata */ return True; } /* Limitazione valli a fase minima con calcolo del valore RMS sulla banda indicata */ /* Versione basata sulla trasformata di Hilbert */ Boolean HMPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; DLReal * FFTArray3; int FS; int I; int J; DLReal RMSLevel; DLReal DLSLevel; DLReal DLLevel; DLReal DLGFactor; DLReal DLMFactor = 0; DLReal DLAbs; DLReal DLMin; Boolean LogLimit; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for (FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; if ((FFTArray3 = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < SigLen;I++) FFTArray1[I] = Sig[I]; /* Azzera la parte rimanente */ for (I = SigLen;I < FS;I++) FFTArray1[I] = (DLReal) 0.0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray1,FS,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello minimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MinGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (DLStart >= (DLReal) 1.0) { /* Scansione per troncatura guadagno */ LogLimit = False; for (I = 0;I < FS;I++) { DLAbs = std::abs(FFTArray1[I]); if (DLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { if (DLAbs < RMSLevel) FFTArray3[I] = (DLReal) RMSLevel / DLAbs; else FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = std::log(FFTArray3[I]); } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } else { /* Determina i fattori per la limitazione guadagno */ DLSLevel = RMSLevel / DLStart; DLGFactor = DLSLevel - RMSLevel; DLMin = (DLReal) -1.0; /* Scansione per limitazione guadagno */ LogLimit = False; for (I = 0; I < FS; I++) { DLAbs = std::abs(FFTArray1[I]); if (DLAbs < DLSLevel) { /* Verifica se gi disponibile il minimo locale */ if (DLMin < (DLReal) 0.0) { /* Cerca il minimo locale */ DLMin = DLAbs; DLLevel = DLAbs; for (J = I + 1; J < FS && DLLevel < DLSLevel; J++) { if (DLLevel < DLMin) DLMin = DLLevel; DLLevel = std::abs(FFTArray1[J]); } /* Verifica se il minimo locale inferiore al livello minimo e ricalcola i fattori di compressione */ if (DLMin < RMSLevel) DLMFactor = DLSLevel - DLMin; else DLMFactor = DLSLevel - RMSLevel; } /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - DLAbs) / DLMFactor; DLLevel = DLSLevel - DLGFactor * DLLevel; if (DLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { FFTArray3[I] = (DLReal) DLLevel / DLAbs; FFTArray2[I] = std::log(FFTArray3[I]); } } else { DLMin = (DLReal) -1.0; FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = (DLReal) 0.0; } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } /* Calcola la fase per il filtro a fase minima */ IFft(FFTArray2,FS); for (I = 1 + FS / 2; I < FS;I++) FFTArray2[I] = -FFTArray2[I]; FFTArray2[0] = (DLReal) 0.0; FFTArray2[FS / 2] = (DLReal) 0.0; Fft(FFTArray2,FS); /* Effettua la convoluzione con il sistema inverso a fase minima */ for (I = 0;I < FS;I++) FFTArray1[I] *= FFTArray3[I] * std::exp(FFTArray2[I]); /* Determina la risposta del sistema */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray1[I]); /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; delete[] FFTArray3; /* Operazione completata */ return True; } /* Limitazione valli a fase minima con calcolo del valore RMS sulla banda indicata */ /* Versione basata sulla trasformata di Hilbert */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1HMPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; DLReal * FFTArray3; int FS; int I; DLReal RMSLevel; DLReal DLSLevel; DLReal DLLevel; DLReal DLGFactor; DLReal DLAbs; Boolean LogLimit; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for (FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; if ((FFTArray3 = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < SigLen;I++) FFTArray1[I] = Sig[I]; /* Azzera la parte rimanente */ for (I = SigLen;I < FS;I++) FFTArray1[I] = (DLReal) 0.0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray1,FS,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello minimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MinGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (DLStart >= (DLReal) 1.0) { /* Scansione per troncatura guadagno */ LogLimit = False; for (I = 0;I < FS;I++) { DLAbs = std::abs(FFTArray1[I]); if (DLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { if (DLAbs < RMSLevel) FFTArray3[I] = (DLReal) RMSLevel / DLAbs; else FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = std::log(FFTArray3[I]); } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } else { /* Determina i fattori per la limitazione guadagno */ DLSLevel = RMSLevel / DLStart; DLGFactor = DLSLevel - RMSLevel; /* Scansione per limitazione guadagno */ LogLimit = False; for (I = 0; I < FS; I++) { DLAbs = std::abs(FFTArray1[I]); if (DLAbs < DLSLevel) { /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - DLAbs) / DLGFactor; DLLevel = DLLevel / (((DLReal) 1.0) + DLLevel); DLLevel = DLSLevel - DLGFactor * DLLevel; if (DLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { FFTArray3[I] = (DLReal) DLLevel / DLAbs; FFTArray2[I] = std::log(FFTArray3[I]); } } else { FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = (DLReal) 0.0; } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } /* Calcola la fase per il filtro a fase minima */ IFft(FFTArray2,FS); for (I = 1 + FS / 2; I < FS;I++) FFTArray2[I] = -FFTArray2[I]; FFTArray2[0] = (DLReal) 0.0; FFTArray2[FS / 2] = (DLReal) 0.0; Fft(FFTArray2,FS); /* Effettua la convoluzione con il sistema inverso a fase minima */ for (I = 0;I < FS;I++) FFTArray1[I] *= FFTArray3[I] * std::exp(FFTArray2[I]); /* Determina la risposta del sistema */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray1[I]); /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; delete[] FFTArray3; /* Operazione completata */ return True; } /* Limitazione picchi a fase lineare con calcolo del valore RMS sull banda indicata */ Boolean LPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { int FFTSize; int I; int J; DLComplex * FFTArray; DLReal RMSLevel; DLReal PLSLevel; DLReal PLLevel; DLReal PLGFactor; DLReal PLMFactor = 0; DLReal PLAbs; DLReal PLMax; /* Determina la prima potenza di 2 >= SigLen */ if (MExp >= 0) { /* Determina la prima potenza di 2 >= SigLen */ for(FFTSize = 1;FFTSize <= SigLen;FFTSize <<= 1); FFTSize *= 1 << MExp; } else FFTSize = SigLen; /* Alloca l'array per l'fft */ FFTArray = new DLComplex[FFTSize]; if (FFTArray == NULL) return False; /* Copia il segnale nell'array */ for (I = 0;I < SigLen;I++) FFTArray[I] = Sig[I]; for (I = SigLen;I < FFTSize;I++) FFTArray[I] = (DLReal) 0.0; /* Effettua l'fft del segnale */ Fft(FFTArray,FFTSize); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray,FFTSize,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello massimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MaxGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (PLStart >= (DLReal) 1.0) { /* Scansione per troncatura guadagno */ for (I = 0; I < FFTSize; I++) { PLAbs = std::abs(FFTArray[I]); if (PLAbs > RMSLevel) FFTArray[I] = std::polar(RMSLevel,std::arg(FFTArray[I])); } } else { /* Determina i fattori per la limitazione guadagno */ PLSLevel = PLStart * RMSLevel; PLGFactor = RMSLevel - PLSLevel; PLMax = (DLReal) -1.0; /* Scansione per limitazione guadagno */ for (I = 0; I < FFTSize; I++) { PLAbs = std::abs(FFTArray[I]); if (PLAbs > PLSLevel) { /* Verifica se gi disponibile il massimo locale */ if (PLMax < (DLReal) 0.0) { /* Cerca il massimo locale */ PLMax = PLAbs; PLLevel = PLAbs; for (J = I + 1; J < FFTSize && PLLevel > PLSLevel; J++) { if (PLLevel > PLMax) PLMax = PLLevel; PLLevel = std::abs(FFTArray[J]); } /* Verifica se il massimo locale superiore al livello massimo e ricalcola i fattori di compressione */ if (PLMax > RMSLevel) PLMFactor = PLMax - PLSLevel; else PLMFactor = RMSLevel - PLSLevel; } /* Riassegna il guadagno del filtro */ PLLevel = (PLAbs - PLSLevel) / PLMFactor; FFTArray[I] = std::polar(PLSLevel + PLGFactor * PLLevel, std::arg(FFTArray[I])); } else PLMax = (DLReal) -1.0; } } /* Effettua l'fft inversa del segnale */ IFft(FFTArray,FFTSize); /* Ritorna il segnale limitato */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray[I]); /* Dealloca l'array */ delete[] FFTArray; /* Operazione completata */ return True; } /* Limitazione picchi a fase lineare con calcolo del valore RMS sull banda indicata */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1LPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { int FFTSize; int I; DLComplex * FFTArray; DLReal RMSLevel; DLReal PLSLevel; DLReal PLLevel; DLReal PLGFactor; DLReal PLAbs; /* Determina la prima potenza di 2 >= SigLen */ if (MExp >= 0) { /* Determina la prima potenza di 2 >= SigLen */ for(FFTSize = 1;FFTSize <= SigLen;FFTSize <<= 1); FFTSize *= 1 << MExp; } else FFTSize = SigLen; /* Alloca l'array per l'fft */ FFTArray = new DLComplex[FFTSize]; if (FFTArray == NULL) return False; /* Copia il segnale nell'array */ for (I = 0;I < SigLen;I++) FFTArray[I] = Sig[I]; for (I = SigLen;I < FFTSize;I++) FFTArray[I] = (DLReal) 0.0; /* Effettua l'fft del segnale */ Fft(FFTArray,FFTSize); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray,FFTSize,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello massimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MaxGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (PLStart >= (DLReal) 1.0) { /* Scansione per troncatura guadagno */ for (I = 0; I < FFTSize; I++) { PLAbs = std::abs(FFTArray[I]); if (PLAbs > RMSLevel) FFTArray[I] = std::polar(RMSLevel,std::arg(FFTArray[I])); } } else { /* Determina i fattori per la limitazione guadagno */ PLSLevel = PLStart * RMSLevel; PLGFactor = RMSLevel - PLSLevel; /* Scansione per limitazione guadagno */ for (I = 0; I < FFTSize; I++) { PLAbs = std::abs(FFTArray[I]); if (PLAbs > PLSLevel) { /* Riassegna il guadagno del filtro */ PLLevel = (PLAbs - PLSLevel) / PLGFactor; PLLevel = PLLevel / (((DLReal) 1.0) + PLLevel); FFTArray[I] = std::polar(PLSLevel + PLGFactor * PLLevel, std::arg(FFTArray[I])); } } } /* Effettua l'fft inversa del segnale */ IFft(FFTArray,FFTSize); /* Ritorna il segnale limitato */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray[I]); /* Dealloca l'array */ delete[] FFTArray; /* Operazione completata */ return True; } /* Limitazione picchi a fase minima con calcolo del valore RMS sull banda indicata */ /* Versione basata sulla trasformata di Hilbert */ Boolean HMPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; DLReal * FFTArray3; int FS; int I; int J; DLReal RMSLevel; DLReal PLSLevel; DLReal PLLevel; DLReal PLGFactor; DLReal PLMFactor = 0; DLReal PLAbs; DLReal PLMax; Boolean LogLimit; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for (FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; if ((FFTArray3 = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < SigLen;I++) FFTArray1[I] = Sig[I]; /* Azzera la parte rimanente */ for (I = SigLen;I < FS;I++) FFTArray1[I] = (DLReal) 0.0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray1,FS,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello massimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MaxGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (PLStart >= (DLReal) 1.0) { /* Scansione per troncamento guadagno */ LogLimit = False; for (I = 0;I < FS;I++) { PLAbs = std::abs(FFTArray1[I]); if (PLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { if (PLAbs > RMSLevel) FFTArray3[I] = (DLReal) RMSLevel / PLAbs; else FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = std::log(FFTArray3[I]); } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } else { /* Determina i fattori per la limitazione guadagno */ PLSLevel = PLStart * RMSLevel; PLGFactor = RMSLevel - PLSLevel; PLMax = (DLReal) -1.0; /* Scansione per limitazione guadagno */ LogLimit = False; for (I = 0; I < FS; I++) { PLAbs = std::abs(FFTArray1[I]); if (PLAbs > PLSLevel) { /* Verifica se gi disponibile il massimo locale */ if (PLMax < (DLReal) 0.0) { /* Cerca il massimo locale */ PLMax = PLAbs; PLLevel = PLAbs; for (J = I + 1; J < FS && PLLevel > PLSLevel; J++) { if (PLLevel > PLMax) PLMax = PLLevel; PLLevel = std::abs(FFTArray1[J]); } /* Verifica se il massimo locale superiore al livello massimo e ricalcola i fattori di compressione */ if (PLMax > RMSLevel) PLMFactor = PLMax - PLSLevel; else PLMFactor = RMSLevel - PLSLevel; } /* Riassegna il guadagno del filtro */ PLLevel = (PLAbs - PLSLevel) / PLMFactor; PLLevel = PLSLevel + PLGFactor * PLLevel; if (PLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { FFTArray3[I] = (DLReal) PLLevel / PLAbs; FFTArray2[I] = std::log(FFTArray3[I]); } } else { PLMax = (DLReal) -1.0; FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = (DLReal) 0.0; } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } /* Calcola la fase per il filtro a fase minima */ IFft(FFTArray2,FS); for (I = 1 + FS / 2; I < FS;I++) FFTArray2[I] = -FFTArray2[I]; FFTArray2[0] = (DLReal) 0.0; FFTArray2[FS / 2] = (DLReal) 0.0; Fft(FFTArray2,FS); /* Effettua la convoluzione con il sistema inverso a fase minima */ for (I = 0;I < FS;I++) FFTArray1[I] *= FFTArray3[I] * std::exp(FFTArray2[I]); /* Determina la risposta del sistema */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray1[I]); /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; delete[] FFTArray3; /* Operazione completata */ return True; } /* Limitazione picchi a fase minima con calcolo del valore RMS sull banda indicata */ /* Versione basata sulla trasformata di Hilbert */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1HMPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; DLReal * FFTArray3; int FS; int I; DLReal RMSLevel; DLReal PLSLevel; DLReal PLLevel; DLReal PLGFactor; DLReal PLAbs; Boolean LogLimit; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for (FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; if ((FFTArray3 = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < SigLen;I++) FFTArray1[I] = Sig[I]; /* Azzera la parte rimanente */ for (I = SigLen;I < FS;I++) FFTArray1[I] = (DLReal) 0.0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Determina il livello RMS del segnale */ RMSLevel = GetBLFFTRMSLevel(FFTArray1,FS,SampleFreq,StartFreq,EndFreq,W); /* Calcola il livello massimo tenendo conto delle limitazioni di banda */ RMSLevel = (DLReal) (RMSLevel * MaxGain / sqrt(2.0 * (EndFreq - StartFreq) / SampleFreq)); /* Verifica il tipo di limitazione impostata */ if (PLStart >= (DLReal) 1.0) { /* Scansione per troncamento guadagno */ LogLimit = False; for (I = 0;I < FS;I++) { PLAbs = std::abs(FFTArray1[I]); if (PLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { if (PLAbs > RMSLevel) FFTArray3[I] = (DLReal) RMSLevel / PLAbs; else FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = std::log(FFTArray3[I]); } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } else { /* Determina i fattori per la limitazione guadagno */ PLSLevel = PLStart * RMSLevel; PLGFactor = RMSLevel - PLSLevel; /* Scansione per limitazione guadagno */ LogLimit = False; for (I = 0; I < FS; I++) { PLAbs = std::abs(FFTArray1[I]); if (PLAbs > PLSLevel) { /* Riassegna il guadagno del filtro */ PLLevel = (PLAbs - PLSLevel) / PLGFactor; PLLevel = PLLevel / (((DLReal) 1.0) + PLLevel); PLLevel = PLSLevel + PLGFactor * PLLevel; if (PLAbs <= 0) { LogLimit = True; FFTArray3[I] = DRCMaxFloat; FFTArray2[I] = std::log(DRCMaxFloat); } else { FFTArray3[I] = (DLReal) PLLevel / PLAbs; FFTArray2[I] = std::log(FFTArray3[I]); } } else { FFTArray3[I] = (DLReal) 1.0; FFTArray2[I] = (DLReal) 0.0; } } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); } /* Calcola la fase per il filtro a fase minima */ IFft(FFTArray2,FS); for (I = 1 + FS / 2; I < FS;I++) FFTArray2[I] = -FFTArray2[I]; FFTArray2[0] = (DLReal) 0.0; FFTArray2[FS / 2] = (DLReal) 0.0; Fft(FFTArray2,FS); /* Effettua la convoluzione con il sistema inverso a fase minima */ for (I = 0;I < FS;I++) FFTArray1[I] *= FFTArray3[I] * std::exp(FFTArray2[I]); /* Determina la risposta del sistema */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray1[I]); /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; delete[] FFTArray3; /* Operazione completata */ return True; } /* Livellazione norma a fase lineare */ Boolean LPNormFlat(DLReal * Sig,const int SigLen,const DLReal Gain,const DLReal OGainFactor,const int MExp) { int FFTSize; int I; DLComplex * FFTArray; DLReal G; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Determina la prima potenza di 2 >= SigLen */ for(FFTSize = 1;FFTSize <= SigLen;FFTSize <<= 1); FFTSize *= 1 << MExp; } else FFTSize = SigLen; /* Alloca l'array per l'fft */ FFTArray = new DLComplex[FFTSize]; if (FFTArray == NULL) return False; /* Copia il segnale nell'array */ for (I = 0;I < SigLen;I++) FFTArray[I] = Sig[I]; for (I = SigLen;I < FFTSize;I++) FFTArray[I] = (DLReal) 0.0; /* Effettua l'fft del segnale */ Fft(FFTArray,FFTSize); /* Scansione per normalizzazione guadagno */ G = (1 - OGainFactor) * GetRMSLevel(Sig,SigLen); for (I = 0; I < FFTSize; I++) FFTArray[I] = std::polar(Gain * (G + OGainFactor * std::abs(FFTArray[I])), std::arg(FFTArray[I])); /* Effettua l'fft inversa del segnale */ IFft(FFTArray,FFTSize); /* Ritorna il segnale limitato */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray[I]); /* Dealloca l'array */ delete[] FFTArray; /* Operazione completata */ return True; } /* Livellazione norma a fase minima */ /* Versione basato sul calcolo del cepstrum */ Boolean CMPNormFlat(DLReal * Sig,const int SigLen,const DLReal Gain,const DLReal OGainFactor,const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; int FS; int I; DLReal G; Boolean LogLimit; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < SigLen;I++) FFTArray1[I] = Sig[I]; /* Azzera la parte rimanente */ for (I = SigLen;I < FS;I++) FFTArray1[I] = (DLReal) 0.0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Calcola i valori per il cepstrum */ G = OGainFactor * GetRMSLevel(Sig,SigLen); LogLimit = False; for (I = 0;I < FS;I++) if (std::abs(FFTArray1[I]) <= 0) { LogLimit = True; FFTArray2[I] = DRCMaxFloat; } else FFTArray2[I] = std::log(Gain / (G + (1 - OGainFactor) * std::abs(FFTArray1[I]))); /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in cepstrum computation."); /* Calcola il cepstrum */ IFft(FFTArray2,FS); /* Finestra il cepstrum */ for (I = 1; I < FS/2;I++) FFTArray2[I] *= (DLReal) 2.0; for (I = FS/2 + 1; I < FS;I++) FFTArray2[I] = (DLReal) 0.0; /* Calcola la trsformata del cepstrum finestrato */ Fft(FFTArray2,FS); /* Effettua la convoluzione con il sistema inverso a fase minima */ for (I = 0;I < FS;I++) FFTArray1[I] *= std::exp(FFTArray2[I]); /* Determina la risposta del sistema */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray1[I]); /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } /* Livellazione norma a fase minima */ /* Versione basata sulla trasformata di Hilbert */ Boolean HMPNormFlat(DLReal * Sig,const int SigLen,const DLReal Gain,const DLReal OGainFactor,const int MExp) { DLComplex * FFTArray1; DLComplex * FFTArray2; DLReal * FFTArray3; int FS; int I; DLReal G; Boolean LogLimit; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; if ((FFTArray3 = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < SigLen;I++) FFTArray1[I] = Sig[I]; /* Azzera la parte rimanente */ for (I = SigLen;I < FS;I++) FFTArray1[I] = (DLReal) 0.0; /* Trasforma l'array risultante */ Fft(FFTArray1,FS); /* Calcola l'ampiezza per il filtro a fase minima */ G = OGainFactor * GetRMSLevel(Sig,SigLen); LogLimit = False; for (I = 0;I < FS;I++) if (std::abs(FFTArray1[I]) <= 0) { LogLimit = True; FFTArray2[I] = DRCMaxFloat; FFTArray3[I] = (DLReal) 0.0; } else { FFTArray3[I] = (DLReal) Gain / (G + (1 - OGainFactor) * std::abs(FFTArray1[I])); FFTArray2[I] = std::log(FFTArray3[I]); } /* Verifica se si raggiunto il limite */ if (LogLimit == True) sputs("Notice: limit reached in Hilbert filter computation."); /* Calcola la fase per il filtro a fase minima */ IFft(FFTArray2,FS); for (I = 1 + FS / 2; I < FS;I++) FFTArray2[I] = -FFTArray2[I]; FFTArray2[0] = (DLReal) 0.0; FFTArray2[FS / 2] = (DLReal) 0.0; Fft(FFTArray2,FS); /* Effettua la convoluzione con il sistema inverso a fase minima */ for (I = 0;I < FS;I++) FFTArray1[I] *= FFTArray3[I] * std::exp(FFTArray2[I]); /* Determina la risposta del sistema */ IFft(FFTArray1,FS); /* Copia il risultato nell'array destinazione */ for (I = 0;I < SigLen;I++) Sig[I] = std::real(FFTArray1[I]); /* Dealloca gli array */ delete[] FFTArray1; delete[] FFTArray2; delete[] FFTArray3; /* Operazione completata */ return True; } drc-3.2.2/source/hd.h0000644000076400001450000000371613162156312013324 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Deconvoluzione omomorfa */ #ifndef HD_h #define HD_h /* Inclusioni */ #include "dsplib.h" /* Effettua la deconvoluzione omomorfa del segnale In */ /* Versione basata sul calcolo del Cepstrum */ Boolean CepstrumHD(const DLReal * In, DLReal * MPOut, DLReal * EPOut, const int N, const int MExp); /* Effettua la deconvoluzione omomorfa del segnale In */ /* Versione basata sulla trasformata di Hilbert */ Boolean HilbertHD(const DLReal * In, DLReal * MPOut, DLReal * EPOut, const int N, const int MExp); /* Experimental nonsense, ignore */ /* Effettua la decomposizione del segnale In nelle somponenti allmag/allphase */ Boolean AMAPDecomposition(const DLReal * In, DLReal * AMOut, DLReal * APOut, const int N, const int PFactor); /* Effettua la decomposizione del segnale In nelle somponenti no phase/no mag */ Boolean NPNMDecomposition(const DLReal * In, DLReal * NPOut, DLReal * NMOut, const int N, const int PFactor); #endif drc-3.2.2/source/drc.depend0000644000076400001450000000004013165107124014474 0ustar denisitadm# depslib dependency file v1.0 drc-3.2.2/source/psychoacoustic.h0000644000076400001450000000746113162156311015771 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002, 2008 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@neomerica.it ****************************************************************************/ /* Procedure a carattere psicoacustico e relative funzioni di supporto */ #ifndef PsychoAcoustic_h #define PsychoAcoustic_h /* Inclusioni */ #include "dsplib.h" /* Ritorna l'ampiezza di banda a frazioni di ottava per una data frequenza */ DLReal FOctBWidth(const DLReal F,const DLReal FOW); /* Versione della funzione precedente che opera su un array di frequenze */ void AFOctBWidth(const DLReal * F, const int N,const DLReal FOW,DLReal * BW); /* Ritorna l'ampiezza di banda per una data frequenza secondo la scala di Bark */ DLReal BarkBWidth(const DLReal F); /* Versione della funzione precedente che opera su un array di frequenze */ void ABarkBWidth(const DLReal * F, const int N,DLReal * BW); /* Ritorna l'ampiezza di banda per una data frequenza secondo la scala ERB */ DLReal ERBBWidth(const DLReal F); /* Versione della funzione precedente che opera su un array di frequenze */ void AERBBWidth(const DLReal * F, const int N,DLReal * BW); /* Calcola la somma cumnulativa sull'array A. Se l'array S non null la somma cumulativa viene posta nell'array S, altrimenti viene posta direttamente in A sostituendo i valori contenuti */ void CumulativeSum(DLReal * A,const int N,DLReal * S); /* Calcola l'inviluppo spettrale del segnale S con approssimazione dei picchi PDS e risoluzione BW, espressa in frazioni di ottava. Nel caso in cui PDS sia pari a 1.0 esegue il classico smoothing a frazioni di ottava. Nel caso in cui BW sia minore di 0.0 usa la scala di Bark, nel caso in cui BW sia minore di -1.0 usa la scala ERB */ Boolean SpectralEnvelope(const DLReal * S,const int N,const int FS, const DLReal BW,const DLReal PDS,DLReal * SE); /* Tipo filtro target */ typedef enum { MKSETFLinearPhase, MKSETFMinimumPhase } MKSETFType; /* Calcola un filtro target basato sull'inviluppo spettrale. Il filtro ha lunghezza pari a 2 volte la lunghezza del segnale in ingresso e non finestrato */ Boolean MKSETargetFilter(const DLReal * S,const int N,const int FS, const DLReal BW,const DLReal PDS,DLReal * TF,const MKSETFType TFType, const DLReal MinGain,const DLReal DLStart,const int SampleFreq, const DLReal StartFreq,const DLReal EndFreq); /* Versione della funzione precedente che effettua un padding del segnale in ingresso alla prima potenza di due disponibile. Il filtro in uscita ha lunghezza pari a TFN. TFN non pu essere superiore alla lunghezza usata internamente per il calcolo del filtro, quindi 2 * N se MExp < 0, oppure 2 * nextpow2(N) * 2 ^ MExp per MExp >= 0 */ Boolean P2MKSETargetFilter(const DLReal * S,const int N,const int FS, const DLReal BW,const DLReal PDS,DLReal * TF,const MKSETFType TFType, const int MExp,const int TFN, const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq); #endif drc-3.2.2/source/drccfg.cpp0000644000076400001450000012672613162156312014523 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Opzioni di configurazione DRC */ /* Inclusioni */ #include "drccfg.h" #include "baselib.h" #include #include #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Opzioni di configurazione */ CfgParmsType Cfg; /* Definizione struttura file di configurazione */ CfgParameter CfgParmsDef[] = { /* Base configuration */ { (char *) "BCBaseDir",CfgString,&Cfg.BCBaseDir }, { (char *) "BCInFile",CfgString,&Cfg.BCInFile }, { (char *) "BCInFileType",CfgString,&Cfg.BCInFileType }, { (char *) "BCSampleRate",CfgInt,&Cfg.BCSampleRate }, { (char *) "BCImpulseCenterMode",CfgString,&Cfg.BCImpulseCenterMode }, { (char *) "BCImpulseCenter",CfgInt,&Cfg.BCImpulseCenter }, { (char *) "BCInitWindow",CfgInt,&Cfg.BCInitWindow }, { (char *) "BCPreWindowLen",CfgInt,&Cfg.BCPreWindowLen }, { (char *) "BCPreWindowGap",CfgInt,&Cfg.BCPreWindowGap }, { (char *) "BCNormFactor",DRCCfgFloat,&Cfg.BCNormFactor }, { (char *) "BCNormType",CfgString,&Cfg.BCNormType }, /* Mic correction stage */ { (char *) "MCFilterType",CfgString,&Cfg.MCFilterType }, { (char *) "MCInterpolationType",CfgString,&Cfg.MCInterpolationType }, { (char *) "MCMultExponent",CfgInt,&Cfg.MCMultExponent }, { (char *) "MCFilterLen",CfgInt,&Cfg.MCFilterLen }, { (char *) "MCNumPoints",CfgInt,&Cfg.MCNumPoints }, { (char *) "MCPointsFile",CfgString,&Cfg.MCPointsFile }, { (char *) "MCMagType",CfgString,&Cfg.MCMagType }, { (char *) "MCFilterFile",CfgString,&Cfg.MCFilterFile }, { (char *) "MCFilterFileType",CfgString,&Cfg.MCFilterFileType }, { (char *) "MCOutWindow",CfgInt,&Cfg.MCOutWindow }, { (char *) "MCNormFactor",DRCCfgFloat,&Cfg.MCNormFactor }, { (char *) "MCNormType",CfgString,&Cfg.MCNormType }, { (char *) "MCOutFile",CfgString,&Cfg.MCOutFile }, { (char *) "MCOutFileType",CfgString,&Cfg.MCOutFileType }, /* Base configuration dip limiting stage */ { (char *) "BCDLType",CfgString,&Cfg.BCDLType }, { (char *) "BCDLMinGain",DRCCfgFloat,&Cfg.BCDLMinGain }, { (char *) "BCDLStartFreq",DRCCfgFloat,&Cfg.BCDLStartFreq }, { (char *) "BCDLEndFreq",DRCCfgFloat,&Cfg.BCDLEndFreq }, { (char *) "BCDLStart",DRCCfgFloat,&Cfg.BCDLStart }, { (char *) "BCDLMultExponent",CfgInt,&Cfg.BCDLMultExponent }, /* Homomorphic Deconvolution */ { (char *) "HDMultExponent",CfgInt,&Cfg.HDMultExponent }, { (char *) "HDMPNormFactor",DRCCfgFloat,&Cfg.HDMPNormFactor }, { (char *) "HDMPNormType",CfgString,&Cfg.HDMPNormType }, { (char *) "HDMPOutFile",CfgString,&Cfg.HDMPOutFile }, { (char *) "HDMPOutFileType",CfgString,&Cfg.HDMPOutFileType }, { (char *) "HDEPNormFactor",DRCCfgFloat,&Cfg.HDEPNormFactor }, { (char *) "HDEPNormType",CfgString,&Cfg.HDEPNormType }, { (char *) "HDEPOutFile",CfgString,&Cfg.HDEPOutFile }, { (char *) "HDEPOutFileType",CfgString,&Cfg.HDEPOutFileType }, /* Minimum phase prefiltering stage */ { (char *) "MPPrefilterType",CfgString,&Cfg.MPPrefilterType }, { (char *) "MPPrefilterFctn",CfgString,&Cfg.MPPrefilterFctn }, { (char *) "MPWindowGap",CfgInt,&Cfg.MPWindowGap }, { (char *) "MPLowerWindow",CfgInt,&Cfg.MPLowerWindow }, { (char *) "MPUpperWindow",CfgInt,&Cfg.MPUpperWindow }, { (char *) "MPStartFreq",DRCCfgFloat,&Cfg.MPStartFreq }, { (char *) "MPEndFreq",DRCCfgFloat,&Cfg.MPEndFreq }, { (char *) "MPWindowExponent",DRCCfgFloat,&Cfg.MPWindowExponent }, { (char *) "MPFilterLen",CfgInt,&Cfg.MPFilterLen }, { (char *) "MPFSharpness",DRCCfgFloat,&Cfg.MPFSharpness }, { (char *) "MPBandSplit",CfgInt,&Cfg.MPBandSplit }, { (char *) "MPHDRecover",CfgString,&Cfg.MPHDRecover }, { (char *) "MPEPPreserve",CfgString,&Cfg.MPEPPreserve }, { (char *) "MPHDMultExponent",CfgInt,&Cfg.MPHDMultExponent }, { (char *) "MPPFFinalWindow",CfgInt,&Cfg.MPPFFinalWindow }, { (char *) "MPPFNormFactor",DRCCfgFloat,&Cfg.MPPFNormFactor }, { (char *) "MPPFNormType",CfgString,&Cfg.MPPFNormType }, { (char *) "MPPFOutFile",CfgString,&Cfg.MPPFOutFile }, { (char *) "MPPFOutFileType",CfgString,&Cfg.MPPFOutFileType }, /* Dip limiting stage */ { (char *) "DLType",CfgString,&Cfg.DLType }, { (char *) "DLMinGain",DRCCfgFloat,&Cfg.DLMinGain }, { (char *) "DLStartFreq",DRCCfgFloat,&Cfg.DLStartFreq }, { (char *) "DLEndFreq",DRCCfgFloat,&Cfg.DLEndFreq }, { (char *) "DLStart",DRCCfgFloat,&Cfg.DLStart }, { (char *) "DLMultExponent",CfgInt,&Cfg.DLMultExponent }, /* Excess fase phase prefiltering stage */ { (char *) "EPPrefilterType",CfgString,&Cfg.EPPrefilterType }, { (char *) "EPPrefilterFctn",CfgString,&Cfg.EPPrefilterFctn }, { (char *) "EPWindowGap",CfgInt,&Cfg.EPWindowGap }, { (char *) "EPLowerWindow",CfgInt,&Cfg.EPLowerWindow }, { (char *) "EPUpperWindow",CfgInt,&Cfg.EPUpperWindow }, { (char *) "EPStartFreq",DRCCfgFloat,&Cfg.EPStartFreq }, { (char *) "EPEndFreq",DRCCfgFloat,&Cfg.EPEndFreq }, { (char *) "EPWindowExponent",DRCCfgFloat,&Cfg.EPWindowExponent }, { (char *) "EPFilterLen",CfgInt,&Cfg.EPFilterLen }, { (char *) "EPFSharpness",DRCCfgFloat,&Cfg.EPFSharpness }, { (char *) "EPBandSplit",CfgInt,&Cfg.EPBandSplit }, { (char *) "EPPFFlatGain",DRCCfgFloat,&Cfg.EPPFFlatGain }, { (char *) "EPPFOGainFactor",DRCCfgFloat,&Cfg.EPPFOGainFactor }, { (char *) "EPPFFlatType",CfgString,&Cfg.EPPFFlatType }, { (char *) "EPPFFGMultExponent",CfgInt,&Cfg.EPPFFGMultExponent }, { (char *) "EPPFFinalWindow",CfgInt,&Cfg.EPPFFinalWindow }, { (char *) "EPPFNormFactor",DRCCfgFloat,&Cfg.EPPFNormFactor }, { (char *) "EPPFNormType",CfgString,&Cfg.EPPFNormType }, { (char *) "EPPFOutFile",CfgString,&Cfg.EPPFOutFile }, { (char *) "EPPFOutFileType",CfgString,&Cfg.EPPFOutFileType }, /* Prefiltering completion stage */ { (char *) "PCOutWindow",CfgInt,&Cfg.PCOutWindow }, { (char *) "PCNormFactor",DRCCfgFloat,&Cfg.PCNormFactor }, { (char *) "PCNormType",CfgString,&Cfg.PCNormType }, { (char *) "PCOutFile",CfgString,&Cfg.PCOutFile }, { (char *) "PCOutFileType",CfgString,&Cfg.PCOutFileType }, /* Inversion stage */ { (char *) "ISType",CfgString,&Cfg.ISType }, { (char *) "ISPETType",CfgString,&Cfg.ISPETType }, { (char *) "ISPrefilterFctn",CfgString,&Cfg.ISPrefilterFctn }, { (char *) "ISPELowerWindow",CfgInt,&Cfg.ISPELowerWindow }, { (char *) "ISPEUpperWindow",CfgInt,&Cfg.ISPEUpperWindow }, { (char *) "ISPEStartFreq",CfgInt,&Cfg.ISPEStartFreq }, { (char *) "ISPEEndFreq",CfgInt,&Cfg.ISPEEndFreq }, { (char *) "ISPEFilterLen",CfgInt,&Cfg.ISPEFilterLen }, { (char *) "ISPEFSharpness",DRCCfgFloat,&Cfg.ISPEFSharpness }, { (char *) "ISPEBandSplit",CfgInt,&Cfg.ISPEBandSplit }, { (char *) "ISPEWindowExponent",DRCCfgFloat,&Cfg.ISPEWindowExponent }, { (char *) "ISPEOGainFactor",DRCCfgFloat,&Cfg.ISPEOGainFactor }, { (char *) "ISSMPMultExponent",CfgInt,&Cfg.ISSMPMultExponent }, { (char *) "ISOutWindow",CfgInt,&Cfg.ISOutWindow }, { (char *) "ISNormFactor",DRCCfgFloat,&Cfg.ISNormFactor }, { (char *) "ISNormType",CfgString,&Cfg.ISNormType }, { (char *) "ISOutFile",CfgString,&Cfg.ISOutFile }, { (char *) "ISOutFileType",CfgString,&Cfg.ISOutFileType }, /* Psychoacoustic target stage */ { (char *) "PTType",CfgString,&Cfg.PTType }, { (char *) "PTReferenceWindow",CfgInt,&Cfg.PTReferenceWindow }, { (char *) "PTDLType",CfgString,&Cfg.PTDLType }, { (char *) "PTDLMinGain",DRCCfgFloat,&Cfg.PTDLMinGain }, { (char *) "PTDLStart",DRCCfgFloat,&Cfg.PTDLStart }, { (char *) "PTDLStartFreq",DRCCfgFloat,&Cfg.PTDLStartFreq }, { (char *) "PTDLEndFreq",DRCCfgFloat,&Cfg.PTDLEndFreq }, { (char *) "PTDLMultExponent",CfgInt,&Cfg.PTDLMultExponent }, { (char *) "PTBandWidth",DRCCfgFloat,&Cfg.PTBandWidth }, { (char *) "PTPeakDetectionStrength",DRCCfgFloat,&Cfg.PTPeakDetectionStrength }, { (char *) "PTMultExponent",CfgInt,&Cfg.PTMultExponent }, { (char *) "PTFilterLen",CfgInt,&Cfg.PTFilterLen }, { (char *) "PTFilterFile",CfgString,&Cfg.PTFilterFile }, { (char *) "PTFilterFileType",CfgString,&Cfg.PTFilterFileType }, { (char *) "PTNormFactor",DRCCfgFloat,&Cfg.PTNormFactor }, { (char *) "PTNormType",CfgString,&Cfg.PTNormType }, { (char *) "PTOutFile",CfgString,&Cfg.PTOutFile }, { (char *) "PTOutFileType",CfgString,&Cfg.PTOutFileType }, { (char *) "PTOutWindow",CfgInt,&Cfg.PTOutWindow }, /* Peak limiting stage */ { (char *) "PLType",CfgString,&Cfg.PLType }, { (char *) "PLMaxGain",DRCCfgFloat,&Cfg.PLMaxGain }, { (char *) "PLStart",DRCCfgFloat,&Cfg.PLStart }, { (char *) "PLStartFreq",DRCCfgFloat,&Cfg.PLStartFreq }, { (char *) "PLEndFreq",DRCCfgFloat,&Cfg.PLEndFreq }, { (char *) "PLMultExponent",CfgInt,&Cfg.PLMultExponent }, { (char *) "PLOutWindow",CfgInt,&Cfg.PLOutWindow }, { (char *) "PLNormFactor",DRCCfgFloat,&Cfg.PLNormFactor }, { (char *) "PLNormType",CfgString,&Cfg.PLNormType }, { (char *) "PLOutFile",CfgString,&Cfg.PLOutFile }, { (char *) "PLOutFileType",CfgString,&Cfg.PLOutFileType }, /* Ringing truncation stage */ { (char *) "RTType",CfgString,&Cfg.RTType }, { (char *) "RTPrefilterFctn",CfgString,&Cfg.RTPrefilterFctn }, { (char *) "RTWindowGap",CfgInt,&Cfg.RTWindowGap }, { (char *) "RTLowerWindow",CfgInt,&Cfg.RTLowerWindow }, { (char *) "RTUpperWindow",CfgInt,&Cfg.RTUpperWindow }, { (char *) "RTStartFreq",DRCCfgFloat,&Cfg.RTStartFreq }, { (char *) "RTEndFreq",DRCCfgFloat,&Cfg.RTEndFreq }, { (char *) "RTWindowExponent",DRCCfgFloat,&Cfg.RTWindowExponent }, { (char *) "RTFilterLen",CfgInt,&Cfg.RTFilterLen }, { (char *) "RTFSharpness",DRCCfgFloat,&Cfg.RTFSharpness }, { (char *) "RTBandSplit",CfgInt,&Cfg.RTBandSplit }, { (char *) "RTOutWindow",CfgInt,&Cfg.RTOutWindow }, { (char *) "RTNormFactor",DRCCfgFloat,&Cfg.RTNormFactor }, { (char *) "RTNormType",CfgString,&Cfg.RTNormType }, { (char *) "RTOutFile",CfgString,&Cfg.RTOutFile }, { (char *) "RTOutFileType",CfgString,&Cfg.RTOutFileType }, /* Target response stage */ { (char *) "PSFilterType",CfgString,&Cfg.PSFilterType }, { (char *) "PSInterpolationType",CfgString,&Cfg.PSInterpolationType }, { (char *) "PSMultExponent",CfgInt,&Cfg.PSMultExponent }, { (char *) "PSFilterLen",CfgInt,&Cfg.PSFilterLen }, { (char *) "PSNumPoints",CfgInt,&Cfg.PSNumPoints }, { (char *) "PSPointsFile",CfgString,&Cfg.PSPointsFile }, { (char *) "PSMagType",CfgString,&Cfg.PSMagType }, { (char *) "PSOutWindow",CfgInt,&Cfg.PSOutWindow }, { (char *) "PSNormFactor",DRCCfgFloat,&Cfg.PSNormFactor }, { (char *) "PSNormType",CfgString,&Cfg.PSNormType }, { (char *) "PSOutFile",CfgString,&Cfg.PSOutFile }, { (char *) "PSOutFileType",CfgString,&Cfg.PSOutFileType }, /* Minimum phase filter extraction stage */ { (char *) "MSMultExponent",CfgInt,&Cfg.MSMultExponent }, { (char *) "MSOutWindow",CfgInt,&Cfg.MSOutWindow }, { (char *) "MSFilterDelay",CfgInt,&Cfg.MSFilterDelay }, { (char *) "MSNormFactor",DRCCfgFloat,&Cfg.MSNormFactor }, { (char *) "MSNormType",CfgString,&Cfg.MSNormType }, { (char *) "MSOutFile",CfgString,&Cfg.MSOutFile }, { (char *) "MSOutFileType",CfgString,&Cfg.MSOutFileType }, /* Test convolution stage */ { (char *) "TCNormFactor",DRCCfgFloat,&Cfg.TCNormFactor }, { (char *) "TCNormType",CfgString,&Cfg.TCNormType }, { (char *) "TCOutFile",CfgString,&Cfg.TCOutFile }, { (char *) "TCOutFileType",CfgString,&Cfg.TCOutFileType }, { (char *) "TCOWFile",CfgString,&Cfg.TCOWFile }, { (char *) "TCOWFileType",CfgString,&Cfg.TCOWFileType }, { (char *) "TCOWNormFactor",DRCCfgFloat,&Cfg.TCOWNormFactor }, { (char *) "TCOWNormType",CfgString,&Cfg.TCOWNormType }, { (char *) "TCOWSkip",CfgInt,&Cfg.TCOWSkip }, { (char *) "TCOWPrewindow",CfgInt,&Cfg.TCOWPrewindow }, { (char *) "TCOWLength",CfgInt,&Cfg.TCOWLength }, /* Chiusura lista parametri */ {NULL, CfgEnd, NULL} }; /* Elenco dei parametri di configurazione che richiedono 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 CfgParameter * CfgParmsDef, const char * ParmName) { int P = 0; while (CfgParmsDef[P].PType != CfgEnd) { if (strcmp(CfgParmsDef[P].PName,ParmName) == 0) return P; P++; } return -1; } /* Impostazione directory base di lavoro */ int SetupDRCCfgBaseDir(CfgParmsType * DRCCfg, const CfgParameter * 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].PValue) != NULL)) { /* Aggiunge la directory base al parametro */ S = StrJoin(DRCCfg->BCBaseDir, (char *) (* ((void **) CfgParmsDef[P].PValue))); /* Verifica che la concatenazione sia riuscita */ if (S == NULL) return 1; /* Dealloca la stringa precedente */ free(*((void **) CfgParmsDef[P].PValue)); /* Sostituisce la stringa precedente */ *((void **) CfgParmsDef[P].PValue) = (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' && DRCCfg->BCDLType[0] != 'P' && DRCCfg->BCDLType[0] != 'W') { 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' && DRCCfg->DLType[0] != 'P' && DRCCfg->DLType[0] != 'W') { 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->ISPEUpperWindow >= DRCCfg->ISPELowerWindow) { sputs("IS->ISPEUpperWindow: ISPELowerWindow must be greater than ISPEUpperWindow."); 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' && DRCCfg->PTDLType[0] != 'P' && DRCCfg->PTDLType[0] != 'W') { 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' && DRCCfg->PLType[0] != 'P' && DRCCfg->PLType[0] != 'W') { 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; } drc-3.2.2/source/level.h0000644000076400001450000001321013162156312014026 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Funzioni correzione e gestione livello del segnale */ #ifndef Level_h #define Level_h /* Inclusioni */ #include "dsplib.h" /* Calola il valore RMS del segnale Sig */ DLReal GetRMSLevel(const DLReal * Sig,const int SigLen); /* Calola il valore RMS del segnale Sig sulla banda di frequenze indicate con pesatura in frequenza pari a 1/(f^w). Per W = 0 calcola il normale valore RMS, per W = 1 assegna peso uguale in potenza per ottava/decade. */ DLReal GetBLRMSLevel(const DLReal * Sig,const int SigLen,const int SampleFreq, const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Calola il valore RMS del segnale trasformato FFTArray sulla banda di frequenze indicate con pesatura in frequenza pari a 1/(f^w). Per W = 0 calcola il normale valore RMS, per W = 1 assegna peso uguale in potenza per ottava/decade. */ DLReal GetBLFFTRMSLevel(const DLComplex * FFTArray,const int FFTSize,const int SampleFreq, const DLReal StartFreq,const DLReal EndFreq,const DLReal W); /* Tipi normalizzazione */ typedef enum { NormMax = 'M', NormSum = 'S', NormEuclidean = 'E', NormFFTPeak = 'P' } NormType; /* Effettua la normalizzazione del segnale al valore indicato e secondo il metodo indicato */ Boolean SigNormalize(DLReal * Sig,const int SigLen,const DLReal NormFactor, const NormType TNorm); /* Limitazione valli a fase lineare con calcolo del valore RMS sull banda indicata */ Boolean LPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Limitazione valli a fase lineare con calcolo del valore RMS sull banda indicata */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1LPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Limitazione valli a fase minima con calcolo del valore RMS sull banda indicata */ /* Versione basata sulla trasformata di Hilbert */ Boolean HMPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Limitazione valli a fase minima con calcolo del valore RMS sull banda indicata */ /* Versione basata sulla trasformata di Hilbert */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1HMPDipLimit(DLReal * Sig,const int SigLen,const DLReal MinGain,const DLReal DLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Limitazione picchi a fase lineare con calcolo del valore RMS sull banda indicata */ Boolean LPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Limitazione picchi a fase lineare con calcolo del valore RMS sull banda indicata */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1LPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Limitazione picchi a fase minima con calcolo del valore RMS sull banda indicata */ /* Versione basata sulla trasformata di Hilbert */ Boolean HMPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Limitazione picchi a fase minima con calcolo del valore RMS sull banda indicata */ /* Versione basata sulla trasformata di Hilbert */ /* Versione con mantenimento continuit della derivata prima nei punti di limitazione */ Boolean C1HMPPeakLimit(DLReal * Sig,const int SigLen,const DLReal MaxGain,const DLReal PLStart, const int SampleFreq,const DLReal StartFreq,const DLReal EndFreq,const DLReal W,const int MExp); /* Livellazione norma a fase lineare */ Boolean LPNormFlat(DLReal * Sig,const int SigLen,const DLReal Gain,const DLReal OGainFactor,const int MExp); /* Livellazione norma a fase minima */ /* Versione basato sul calcolo del cepstrum */ Boolean CMPNormFlat(DLReal * Sig,const int SigLen,const DLReal Gain,const DLReal OGainFactor,const int MExp); /* Livellazione norma a fase minima */ /* Versione basata sulla trasformata di Hilbert */ Boolean HMPNormFlat(DLReal * Sig,const int SigLen,const DLReal Gain,const DLReal OGainFactor,const int MExp); #endif drc-3.2.2/source/fftsg_h.c0000644000076400001450000026033410350310446014341 0ustar denisitadm#include "fftsg_h.h" /* Fast Fourier/Cosine/Sine Transform dimension :one data length :power of 2 decimation :frequency radix :split-radix data :inplace table :not use functions cdft: Complex Discrete Fourier Transform rdft: Real Discrete Fourier Transform ddct: Discrete Cosine Transform ddst: Discrete Sine Transform dfct: Cosine Transform of RDFT (Real Symmetric DFT) dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) function prototypes void cdft(int, int, double *); void rdft(int, int, double *); void ddct(int, int, double *); void ddst(int, int, double *); void dfct(int, double *); void dfst(int, double *); macro definitions USE_CDFT_PTHREADS : default=not defined CDFT_THREADS_BEGIN_N : must be >= 512, default=8192 CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536 USE_CDFT_WINTHREADS : default=not defined CDFT_THREADS_BEGIN_N : must be >= 512, default=32768 CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288 -------- Complex DFT (Discrete Fourier Transform) -------- [definition] X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k cdft(2*n, 1, a); cdft(2*n, -1, a); [parameters] 2*n :data length (int) n >= 1, n = power of 2 a[0...2*n-1] :input/output data (double *) input data a[2*j] = Re(x[j]), a[2*j+1] = Im(x[j]), 0<=j RDFT R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k rdft(n, 1, a); rdft(n, -1, a); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[2*k] = R[k], 0<=k input data a[2*j] = R[j], 0<=j IDCT (excluding scale) C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k ddct(n, 1, a); ddct(n, -1, a); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = C[k], 0<=k IDST (excluding scale) S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 ddst(n, 1, a); ddst(n, -1, a); [parameters] n :data length (int) n >= 2, n = power of 2 a[0...n-1] :input/output data (double *) input data a[j] = A[j], 0 output data a[k] = S[k], 0= 2, n = power of 2 a[0...n] :input/output data (double *) output data a[k] = C[k], 0<=k<=n [remark] Inverse of a[0] *= 0.5; a[n] *= 0.5; dfct(n, a); is a[0] *= 0.5; a[n] *= 0.5; dfct(n, a); for (j = 0; j <= n; j++) { a[j] *= 2.0 / n; } . -------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- [definition] S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 a[0...n-1] :input/output data (double *) output data a[k] = S[k], 0= 0) { cftfsub(n, a); } else { cftbsub(n, a); } } void rdft(int n, int isgn, DLReal *a) { void cftfsub(int n, DLReal *a); void cftbsub(int n, DLReal *a); void rftfsub(int n, DLReal *a); void rftbsub(int n, DLReal *a); DLReal xi; if (isgn >= 0) { if (n > 4) { cftfsub(n, a); rftfsub(n, a); } else if (n == 4) { cftfsub(n, a); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; } else { a[1] = ((DLReal) 0.5) * (a[0] - a[1]); a[0] -= a[1]; if (n > 4) { rftbsub(n, a); cftbsub(n, a); } else if (n == 4) { cftbsub(n, a); } } } void ddct(int n, int isgn, DLReal *a) { void cftfsub(int n, DLReal *a); void cftbsub(int n, DLReal *a); void rftfsub(int n, DLReal *a); void rftbsub(int n, DLReal *a); void dctsub(int n, DLReal *a); void dctsub4(int n, DLReal *a); int j; DLReal xr; if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = a[j] - a[j - 1]; a[j] += a[j - 1]; } a[1] = a[0] - xr; a[0] += xr; if (n > 4) { rftbsub(n, a); cftbsub(n, a); } else if (n == 4) { cftbsub(n, a); } } if (n > 4) { dctsub(n, a); } else { dctsub4(n, a); } if (isgn >= 0) { if (n > 4) { cftfsub(n, a); rftfsub(n, a); } else if (n == 4) { cftfsub(n, a); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = a[j] - a[j + 1]; a[j] += a[j + 1]; } a[n - 1] = xr; } } void ddst(int n, int isgn, DLReal *a) { void cftfsub(int n, DLReal *a); void cftbsub(int n, DLReal *a); void rftfsub(int n, DLReal *a); void rftbsub(int n, DLReal *a); void dstsub(int n, DLReal *a); void dstsub4(int n, DLReal *a); int j; DLReal xr; if (isgn < 0) { xr = a[n - 1]; for (j = n - 2; j >= 2; j -= 2) { a[j + 1] = -a[j] - a[j - 1]; a[j] -= a[j - 1]; } a[1] = a[0] + xr; a[0] -= xr; if (n > 4) { rftbsub(n, a); cftbsub(n, a); } else if (n == 4) { cftbsub(n, a); } } if (n > 4) { dstsub(n, a); } else { dstsub4(n, a); } if (isgn >= 0) { if (n > 4) { cftfsub(n, a); rftfsub(n, a); } else if (n == 4) { cftfsub(n, a); } xr = a[0] - a[1]; a[0] += a[1]; for (j = 2; j < n; j += 2) { a[j - 1] = -a[j] - a[j + 1]; a[j] -= a[j + 1]; } a[n - 1] = -xr; } } void dfct(int n, DLReal *a) { void ddct(int n, int isgn, DLReal *a); void bitrv1(int n, DLReal *a); int j, k, m, mh; DLReal xr, xi, yr, yi, an; m = n >> 1; for (j = 0; j < m; j++) { k = n - j; xr = a[j] + a[k]; a[j] -= a[k]; a[k] = xr; } an = a[n]; while (m >= 2) { ddct(m, 1, a); if (m > 2) { bitrv1(m, a); } mh = m >> 1; xi = a[m]; a[m] = a[0]; a[0] = an - xi; an += xi; for (j = 1; j < mh; j++) { k = m - j; xr = a[m + k]; xi = a[m + j]; yr = a[j]; yi = a[k]; a[m + j] = yr; a[m + k] = yi; a[j] = xr - xi; a[k] = xr + xi; } xr = a[mh]; a[mh] = a[m + mh]; a[m + mh] = xr; m = mh; } xi = a[1]; a[1] = a[0]; a[0] = an + xi; a[n] = an - xi; if (n > 2) { bitrv1(n, a); } } void dfst(int n, DLReal *a) { void ddst(int n, int isgn, DLReal *a); void bitrv1(int n, DLReal *a); int j, k, m, mh; DLReal xr, xi, yr, yi; m = n >> 1; for (j = 1; j < m; j++) { k = n - j; xr = a[j] - a[k]; a[j] += a[k]; a[k] = xr; } a[0] = a[m]; while (m >= 2) { ddst(m, 1, a); if (m > 2) { bitrv1(m, a); } mh = m >> 1; for (j = 1; j < mh; j++) { k = m - j; xr = a[m + k]; xi = a[m + j]; yr = a[j]; yi = a[k]; a[m + j] = yr; a[m + k] = yi; a[j] = xr + xi; a[k] = xr - xi; } a[m] = a[0]; a[0] = a[m + mh]; a[m + mh] = a[mh]; m = mh; } a[1] = a[0]; a[0] = 0; if (n > 2) { bitrv1(n, a); } } /* -------- child routines -------- */ #include #ifndef M_PI_2 #define M_PI_2 ((DLReal) 1.570796326794896619231321691639751442098584699687) #endif #ifndef WR5000 /* cos(M_PI_2*0.5000) */ #define WR5000 ((DLReal) 0.707106781186547524400844362104849039284835937688) #endif #ifndef WR2500 /* cos(M_PI_2*0.2500) */ #define WR2500 ((DLReal) 0.923879532511286756128183189396788286822416625863) #endif #ifndef WI2500 /* sin(M_PI_2*0.2500) */ #define WI2500 ((DLReal) 0.382683432365089771728459984030398866761344562485) #endif #ifndef WR1250 /* cos(M_PI_2*0.1250) */ #define WR1250 ((DLReal) 0.980785280403230449126182236134239036973933730893) #endif #ifndef WI1250 /* sin(M_PI_2*0.1250) */ #define WI1250 ((DLReal) 0.195090322016128267848284868477022240927691617751) #endif #ifndef WR3750 /* cos(M_PI_2*0.3750) */ #define WR3750 ((DLReal) 0.831469612302545237078788377617905756738560811987) #endif #ifndef WI3750 /* sin(M_PI_2*0.3750) */ #define WI3750 ((DLReal) 0.555570233019602224742830813948532874374937190754) #endif #ifdef USE_CDFT_PTHREADS #define USE_CDFT_THREADS #ifndef CDFT_THREADS_BEGIN_N #define CDFT_THREADS_BEGIN_N 8192 #endif #ifndef CDFT_4THREADS_BEGIN_N #define CDFT_4THREADS_BEGIN_N 65536 #endif #include #include #include #define cdft_thread_t pthread_t #define cdft_thread_create(thp,func,argp) { \ if (pthread_create(thp, NULL, func, (void *) argp) != 0) { \ fprintf(stderr, "cdft thread error\n"); \ exit(1); \ } \ } #define cdft_thread_wait(th) { \ if (pthread_join(th, NULL) != 0) { \ fprintf(stderr, "cdft thread error\n"); \ exit(1); \ } \ } #endif /* USE_CDFT_PTHREADS */ #ifdef USE_CDFT_WINTHREADS #define USE_CDFT_THREADS #ifndef CDFT_THREADS_BEGIN_N #define CDFT_THREADS_BEGIN_N 32768 #endif #ifndef CDFT_4THREADS_BEGIN_N #define CDFT_4THREADS_BEGIN_N 524288 #endif #include #include #include #define cdft_thread_t HANDLE #define cdft_thread_create(thp,func,argp) { \ DWORD thid; \ *(thp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, (LPVOID) argp, 0, &thid); \ if (*(thp) == 0) { \ fprintf(stderr, "cdft thread error\n"); \ exit(1); \ } \ } #define cdft_thread_wait(th) { \ WaitForSingleObject(th, INFINITE); \ CloseHandle(th); \ } #endif /* USE_CDFT_WINTHREADS */ #ifndef CDFT_LOOP_DIV /* control of the CDFT's speed & tolerance */ #define CDFT_LOOP_DIV 32 #endif #ifndef RDFT_LOOP_DIV /* control of the RDFT's speed & tolerance */ #define RDFT_LOOP_DIV 64 #endif #ifndef DCST_LOOP_DIV /* control of the DCT,DST's speed & tolerance */ #define DCST_LOOP_DIV 64 #endif void cftfsub(int n, DLReal *a) { void bitrv2(int n, DLReal *a); void bitrv216(DLReal *a); void bitrv208(DLReal *a); void cftmdl1(int n, DLReal *a); void cftrec4(int n, DLReal *a); void cftleaf(int n, int isplt, DLReal *a); void cftfx41(int n, DLReal *a); void cftf161(DLReal *a); void cftf081(DLReal *a); void cftf040(DLReal *a); void cftx020(DLReal *a); #ifdef USE_CDFT_THREADS void cftrec4_th(int n, DLReal *a); #endif /* USE_CDFT_THREADS */ if (n > 8) { if (n > 32) { cftmdl1(n, a); #ifdef USE_CDFT_THREADS if (n > CDFT_THREADS_BEGIN_N) { cftrec4_th(n, a); } else #endif /* USE_CDFT_THREADS */ if (n > 512) { cftrec4(n, a); } else if (n > 128) { cftleaf(n, 1, a); } else { cftfx41(n, a); } bitrv2(n, a); } else if (n == 32) { cftf161(a); bitrv216(a); } else { cftf081(a); bitrv208(a); } } else if (n == 8) { cftf040(a); } else if (n == 4) { cftx020(a); } } void cftbsub(int n, DLReal *a) { void bitrv2conj(int n, DLReal *a); void bitrv216neg(DLReal *a); void bitrv208neg(DLReal *a); void cftb1st(int n, DLReal *a); void cftrec4(int n, DLReal *a); void cftleaf(int n, int isplt, DLReal *a); void cftfx41(int n, DLReal *a); void cftf161(DLReal *a); void cftf081(DLReal *a); void cftb040(DLReal *a); void cftx020(DLReal *a); #ifdef USE_CDFT_THREADS void cftrec4_th(int n, DLReal *a); #endif /* USE_CDFT_THREADS */ if (n > 8) { if (n > 32) { cftb1st(n, a); #ifdef USE_CDFT_THREADS if (n > CDFT_THREADS_BEGIN_N) { cftrec4_th(n, a); } else #endif /* USE_CDFT_THREADS */ if (n > 512) { cftrec4(n, a); } else if (n > 128) { cftleaf(n, 1, a); } else { cftfx41(n, a); } bitrv2conj(n, a); } else if (n == 32) { cftf161(a); bitrv216neg(a); } else { cftf081(a); bitrv208neg(a); } } else if (n == 8) { cftb040(a); } else if (n == 4) { cftx020(a); } } void bitrv2(int n, DLReal *a) { int j0, k0, j1, k1, l, m, i, j, k, nh; DLReal xr, xi, yr, yi; m = 4; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; if (l == 8) { j0 = 0; for (k0 = 0; k0 < m; k0 += 4) { k = k0; for (j = j0; j < j0 + k0; j += 4) { xr = a[j]; xi = a[j + 1]; yr = a[k]; yi = a[k + 1]; a[j] = yr; a[j + 1] = yi; a[k] = xr; a[k + 1] = xi; j1 = j + m; k1 = k + 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 -= m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 += m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 -= m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 += m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; for (i = nh >> 1; i > (k ^= i); i >>= 1); } k1 = j0 + k0; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += 2 * m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 -= m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - m; k1 += 2 * m - 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; for (i = nh >> 1; i > (j0 ^= i); i >>= 1); } } else { j0 = 0; for (k0 = 0; k0 < m; k0 += 4) { k = k0; for (j = j0; j < j0 + k0; j += 4) { xr = a[j]; xi = a[j + 1]; yr = a[k]; yi = a[k + 1]; a[j] = yr; a[j + 1] = yi; a[k] = xr; a[k + 1] = xi; j1 = j + m; k1 = k + m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; for (i = nh >> 1; i > (k ^= i); i >>= 1); } k1 = j0 + k0; j1 = k1 + 2; k1 += nh; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += m; xr = a[j1]; xi = a[j1 + 1]; yr = a[k1]; yi = a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; for (i = nh >> 1; i > (j0 ^= i); i >>= 1); } } } void bitrv2conj(int n, DLReal *a) { int j0, k0, j1, k1, l, m, i, j, k, nh; DLReal xr, xi, yr, yi; m = 4; for (l = n >> 2; l > 8; l >>= 2) { m <<= 1; } nh = n >> 1; if (l == 8) { j0 = 0; for (k0 = 0; k0 < m; k0 += 4) { k = k0; for (j = j0; j < j0 + k0; j += 4) { xr = a[j]; xi = -a[j + 1]; yr = a[k]; yi = -a[k + 1]; a[j] = yr; a[j + 1] = yi; a[k] = xr; a[k + 1] = xi; j1 = j + m; k1 = k + 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 -= m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 += m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 -= m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 += m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; for (i = nh >> 1; i > (k ^= i); i >>= 1); } k1 = j0 + k0; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += m; k1 += 2 * m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 -= m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= 2; k1 -= nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh + 2; k1 += nh + 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh - m; k1 += 2 * m - 2; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; for (i = nh >> 1; i > (j0 ^= i); i >>= 1); } } else { j0 = 0; for (k0 = 0; k0 < m; k0 += 4) { k = k0; for (j = j0; j < j0 + k0; j += 4) { xr = a[j]; xi = -a[j + 1]; yr = a[k]; yi = -a[k + 1]; a[j] = yr; a[j + 1] = yi; a[k] = xr; a[k + 1] = xi; j1 = j + m; k1 = k + m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += nh; k1 += 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += 2; k1 += nh; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 += m; k1 += m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= nh; k1 -= 2; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; j1 -= m; k1 -= m; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; for (i = nh >> 1; i > (k ^= i); i >>= 1); } k1 = j0 + k0; j1 = k1 + 2; k1 += nh; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; j1 += m; k1 += m; a[j1 - 1] = -a[j1 - 1]; xr = a[j1]; xi = -a[j1 + 1]; yr = a[k1]; yi = -a[k1 + 1]; a[j1] = yr; a[j1 + 1] = yi; a[k1] = xr; a[k1 + 1] = xi; a[k1 + 3] = -a[k1 + 3]; for (i = nh >> 1; i > (j0 ^= i); i >>= 1); } } } void bitrv216(DLReal *a) { DLReal x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; a[2] = x8r; a[3] = x8i; a[4] = x4r; a[5] = x4i; a[6] = x12r; a[7] = x12i; a[8] = x2r; a[9] = x2i; a[10] = x10r; a[11] = x10i; a[14] = x14r; a[15] = x14i; a[16] = x1r; a[17] = x1i; a[20] = x5r; a[21] = x5i; a[22] = x13r; a[23] = x13i; a[24] = x3r; a[25] = x3i; a[26] = x11r; a[27] = x11i; a[28] = x7r; a[29] = x7i; } void bitrv216neg(DLReal *a) { DLReal x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; x8r = a[16]; x8i = a[17]; x9r = a[18]; x9i = a[19]; x10r = a[20]; x10i = a[21]; x11r = a[22]; x11i = a[23]; x12r = a[24]; x12i = a[25]; x13r = a[26]; x13i = a[27]; x14r = a[28]; x14i = a[29]; x15r = a[30]; x15i = a[31]; a[2] = x15r; a[3] = x15i; a[4] = x7r; a[5] = x7i; a[6] = x11r; a[7] = x11i; a[8] = x3r; a[9] = x3i; a[10] = x13r; a[11] = x13i; a[12] = x5r; a[13] = x5i; a[14] = x9r; a[15] = x9i; a[16] = x1r; a[17] = x1i; a[18] = x14r; a[19] = x14i; a[20] = x6r; a[21] = x6i; a[22] = x10r; a[23] = x10i; a[24] = x2r; a[25] = x2i; a[26] = x12r; a[27] = x12i; a[28] = x4r; a[29] = x4i; a[30] = x8r; a[31] = x8i; } void bitrv208(DLReal *a) { DLReal x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; x1r = a[2]; x1i = a[3]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x6r = a[12]; x6i = a[13]; a[2] = x4r; a[3] = x4i; a[6] = x6r; a[7] = x6i; a[8] = x1r; a[9] = x1i; a[12] = x3r; a[13] = x3i; } void bitrv208neg(DLReal *a) { DLReal x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; x1r = a[2]; x1i = a[3]; x2r = a[4]; x2i = a[5]; x3r = a[6]; x3i = a[7]; x4r = a[8]; x4i = a[9]; x5r = a[10]; x5i = a[11]; x6r = a[12]; x6i = a[13]; x7r = a[14]; x7i = a[15]; a[2] = x7r; a[3] = x7i; a[4] = x3r; a[5] = x3i; a[6] = x5r; a[7] = x5i; a[8] = x1r; a[9] = x1i; a[10] = x6r; a[11] = x6i; a[12] = x2r; a[13] = x2i; a[14] = x4r; a[15] = x4i; } void bitrv1(int n, DLReal *a) { int j0, k0, j1, k1, l, m, i, j, k, nh; DLReal x; nh = n >> 1; x = a[1]; a[1] = a[nh]; a[nh] = x; m = 2; for (l = n >> 2; l > 2; l >>= 2) { m <<= 1; } if (l == 2) { j1 = m + 1; k1 = m + nh; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j0 = 0; for (k0 = 2; k0 < m; k0 += 2) { for (i = nh >> 1; i > (j0 ^= i); i >>= 1); k = k0; for (j = j0; j < j0 + k0; j += 2) { x = a[j]; a[j] = a[k]; a[k] = x; j1 = j + m; k1 = k + m; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1 += nh; k1++; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1 -= m; k1 -= m; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1++; k1 += nh; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1 += m; k1 += m; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1 -= nh; k1--; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1 -= m; k1 -= m; x = a[j1]; a[j1] = a[k1]; a[k1] = x; for (i = nh >> 1; i > (k ^= i); i >>= 1); } k1 = j0 + k0; j1 = k1 + 1; k1 += nh; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1 += m; k1 += m; x = a[j1]; a[j1] = a[k1]; a[k1] = x; } } else { j0 = 0; for (k0 = 2; k0 < m; k0 += 2) { for (i = nh >> 1; i > (j0 ^= i); i >>= 1); k = k0; for (j = j0; j < j0 + k0; j += 2) { x = a[j]; a[j] = a[k]; a[k] = x; j1 = j + nh; k1 = k + 1; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1++; k1 += nh; x = a[j1]; a[j1] = a[k1]; a[k1] = x; j1 -= nh; k1--; x = a[j1]; a[j1] = a[k1]; a[k1] = x; for (i = nh >> 1; i > (k ^= i); i >>= 1); } k1 = j0 + k0; j1 = k1 + 1; k1 += nh; x = a[j1]; a[j1] = a[k1]; a[k1] = x; } } } void cftb1st(int n, DLReal *a) { int i, i0, j, j0, j1, j2, j3, m, mh; DLReal ew, w1r, w1i, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i, ss1, ss3; DLReal x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = -a[1] - a[j2 + 1]; x1r = a[0] - a[j2]; x1i = -a[1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; a[j2] = x1r + x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r - x3i; a[j3 + 1] = x1i - x3r; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; ew = M_PI_2 / m; w1r = (DLReal) cos(2 * ew); w1i = (DLReal) sin(2 * ew); wk1r = w1r; wk1i = w1i; ss1 = 2 * w1i; wk3i = 2 * ss1 * wk1r; wk3r = wk1r - wk3i * wk1i; wk3i = wk1i - wk3i * wk1r; ss3 = 2 * wk3i; i = 0; for (;;) { i0 = i + 4 * CDFT_LOOP_DIV; if (i0 > mh - 4) { i0 = mh - 4; } for (j = i + 2; j < i0; j += 4) { wd1r -= ss1 * wk1i; wd1i += ss1 * wk1r; wd3r -= ss3 * wk3i; wd3i += ss3 * wk3r; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = -a[j + 1] - a[j2 + 1]; x1r = a[j] - a[j2]; x1i = -a[j + 1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = a[j + 2] + a[j2 + 2]; x0i = -a[j + 3] - a[j2 + 3]; x1r = a[j + 2] - a[j2 + 2]; x1i = -a[j + 3] + a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j + 2] = x0r + x2r; a[j + 3] = x0i - x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = a[j0 - 2] + a[j2 - 2]; x0i = -a[j0 - 1] - a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i - x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; wk1r -= ss1 * wd1i; wk1i += ss1 * wd1r; wk3r -= ss3 * wd3i; wk3i += ss3 * wd3r; } if (i0 == mh - 4) { break; } wd1r = (DLReal) cos(ew * i0); wd1i = (DLReal) sin(ew * i0); wd3i = 4 * wd1i * wd1r; wd3r = wd1r - wd3i * wd1i; wd3i = wd1i - wd3i * wd1r; wk1r = w1r * wd1r - w1i * wd1i; wk1i = w1r * wd1i + w1i * wd1r; wk3i = 4 * wk1i * wk1r; wk3r = wk1r - wk3i * wk1i; wk3i = wk1i - wk3i * wk1r; i = i0; } wd1r = WR5000; j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = -a[j0 - 1] - a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = -a[j0 - 1] + a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i - x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = -a[j0 + 1] - a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = -a[j0 + 1] + a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i - x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2] = wd1r * (x0r - x0i); a[j2 + 1] = wd1r * (x0i + x0r); x0r = x1r - x3i; x0i = x1i - x3r; a[j3] = -wd1r * (x0r + x0i); a[j3 + 1] = -wd1r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = -a[j0 + 3] - a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = -a[j0 + 3] + a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i - x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i + x2i; x0r = x1r + x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r - x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } #ifdef USE_CDFT_THREADS struct cdft_arg_st { int n0; int n; DLReal *a; }; typedef struct cdft_arg_st cdft_arg_t; void cftrec4_th(int n, DLReal *a) { void *cftrec1_th(void *p); void *cftrec2_th(void *p); int i, idiv4, m, nthread; cdft_thread_t th[4]; cdft_arg_t ag[4]; nthread = 2; idiv4 = 0; m = n >> 1; if (n > CDFT_4THREADS_BEGIN_N) { nthread = 4; idiv4 = 1; m >>= 1; } for (i = 0; i < nthread; i++) { ag[i].n0 = n; ag[i].n = m; ag[i].a = &a[i * m]; if (i != idiv4) { cdft_thread_create(&th[i], cftrec1_th, &ag[i]); } else { cdft_thread_create(&th[i], cftrec2_th, &ag[i]); } } for (i = 0; i < nthread; i++) { cdft_thread_wait(th[i]); } } void *cftrec1_th(void *p) { int cfttree(int n, int j, int k, DLReal *a); void cftleaf(int n, int isplt, DLReal *a); void cftmdl1(int n, DLReal *a); int isplt, j, k, m, n, n0; DLReal *a; n0 = ((cdft_arg_t *) p)->n0; n = ((cdft_arg_t *) p)->n; a = ((cdft_arg_t *) p)->a; m = n0; while (m > 512) { m >>= 2; cftmdl1(m, &a[n - m]); } cftleaf(m, 1, &a[n - m]); k = 0; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a); cftleaf(m, isplt, &a[j - m]); } return (void *) 0; } void *cftrec2_th(void *p) { int cfttree(int n, int j, int k, DLReal *a); void cftleaf(int n, int isplt, DLReal *a); void cftmdl2(int n, DLReal *a); int isplt, j, k, m, n, n0; DLReal *a; n0 = ((cdft_arg_t *) p)->n0; n = ((cdft_arg_t *) p)->n; a = ((cdft_arg_t *) p)->a; k = 1; m = n0; while (m > 512) { m >>= 2; k <<= 2; cftmdl2(m, &a[n - m]); } cftleaf(m, 0, &a[n - m]); k >>= 1; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a); cftleaf(m, isplt, &a[j - m]); } return (void *) 0; } #endif /* USE_CDFT_THREADS */ void cftrec4(int n, DLReal *a) { int cfttree(int n, int j, int k, DLReal *a); void cftleaf(int n, int isplt, DLReal *a); void cftmdl1(int n, DLReal *a); int isplt, j, k, m; m = n; while (m > 512) { m >>= 2; cftmdl1(m, &a[n - m]); } cftleaf(m, 1, &a[n - m]); k = 0; for (j = n - m; j > 0; j -= m) { k++; isplt = cfttree(m, j, k, a); cftleaf(m, isplt, &a[j - m]); } } int cfttree(int n, int j, int k, DLReal *a) { void cftmdl1(int n, DLReal *a); void cftmdl2(int n, DLReal *a); int i, isplt, m; if ((k & 3) != 0) { isplt = k & 1; if (isplt != 0) { cftmdl1(n, &a[j - n]); } else { cftmdl2(n, &a[j - n]); } } else { m = n; for (i = k; (i & 3) == 0; i >>= 2) { m <<= 2; } isplt = i & 1; if (isplt != 0) { while (m > 128) { cftmdl1(m, &a[j - m]); m >>= 2; } } else { while (m > 128) { cftmdl2(m, &a[j - m]); m >>= 2; } } } return isplt; } void cftleaf(int n, int isplt, DLReal *a) { void cftmdl1(int n, DLReal *a); void cftmdl2(int n, DLReal *a); void cftf161(DLReal *a); void cftf162(DLReal *a); void cftf081(DLReal *a); void cftf082(DLReal *a); if (n == 512) { cftmdl1(128, a); cftf161(a); cftf162(&a[32]); cftf161(&a[64]); cftf161(&a[96]); cftmdl2(128, &a[128]); cftf161(&a[128]); cftf162(&a[160]); cftf161(&a[192]); cftf162(&a[224]); cftmdl1(128, &a[256]); cftf161(&a[256]); cftf162(&a[288]); cftf161(&a[320]); cftf161(&a[352]); if (isplt != 0) { cftmdl1(128, &a[384]); cftf161(&a[480]); } else { cftmdl2(128, &a[384]); cftf162(&a[480]); } cftf161(&a[384]); cftf162(&a[416]); cftf161(&a[448]); } else { cftmdl1(64, a); cftf081(a); cftf082(&a[16]); cftf081(&a[32]); cftf081(&a[48]); cftmdl2(64, &a[64]); cftf081(&a[64]); cftf082(&a[80]); cftf081(&a[96]); cftf082(&a[112]); cftmdl1(64, &a[128]); cftf081(&a[128]); cftf082(&a[144]); cftf081(&a[160]); cftf081(&a[176]); if (isplt != 0) { cftmdl1(64, &a[192]); cftf081(&a[240]); } else { cftmdl2(64, &a[192]); cftf082(&a[240]); } cftf081(&a[192]); cftf082(&a[208]); cftf081(&a[224]); } } void cftmdl1(int n, DLReal *a) { int i, i0, j, j0, j1, j2, j3, m, mh; DLReal ew, w1r, w1i, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i, ss1, ss3; DLReal x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; mh = n >> 3; m = 2 * mh; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] + a[j2]; x0i = a[1] + a[j2 + 1]; x1r = a[0] - a[j2]; x1i = a[1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; a[j2] = x1r - x3i; a[j2 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; wd1r = 1; wd1i = 0; wd3r = 1; wd3i = 0; ew = M_PI_2 / m; w1r = (DLReal) cos(2 * ew); w1i = (DLReal) sin(2 * ew); wk1r = w1r; wk1i = w1i; ss1 = 2 * w1i; wk3i = 2 * ss1 * wk1r; wk3r = wk1r - wk3i * wk1i; wk3i = wk1i - wk3i * wk1r; ss3 = 2 * wk3i; i = 0; for (;;) { i0 = i + 4 * CDFT_LOOP_DIV; if (i0 > mh - 4) { i0 = mh - 4; } for (j = i + 2; j < i0; j += 4) { wd1r -= ss1 * wk1i; wd1i += ss1 * wk1r; wd3r -= ss3 * wk3i; wd3i += ss3 * wk3r; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] + a[j2]; x0i = a[j + 1] + a[j2 + 1]; x1r = a[j] - a[j2]; x1i = a[j + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1r * x0r - wk1i * x0i; a[j2 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r + wk3i * x0i; a[j3 + 1] = wk3r * x0i - wk3i * x0r; x0r = a[j + 2] + a[j2 + 2]; x0i = a[j + 3] + a[j2 + 3]; x1r = a[j + 2] - a[j2 + 2]; x1i = a[j + 3] - a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j + 2] = x0r + x2r; a[j + 3] = x0i + x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 + 2] = wd1r * x0r - wd1i * x0i; a[j2 + 3] = wd1r * x0i + wd1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 + 2] = wd3r * x0r + wd3i * x0i; a[j3 + 3] = wd3r * x0i - wd3i * x0r; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wk1i * x0r - wk1r * x0i; a[j2 + 1] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3i * x0r + wk3r * x0i; a[j3 + 1] = wk3i * x0i - wk3r * x0r; x0r = a[j0 - 2] + a[j2 - 2]; x0i = a[j0 - 1] + a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i + x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 - 2] = wd1i * x0r - wd1r * x0i; a[j2 - 1] = wd1i * x0i + wd1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 - 2] = wd3i * x0r + wd3r * x0i; a[j3 - 1] = wd3i * x0i - wd3r * x0r; wk1r -= ss1 * wd1i; wk1i += ss1 * wd1r; wk3r -= ss3 * wd3i; wk3i += ss3 * wd3r; } if (i0 == mh - 4) { break; } wd1r = (DLReal) cos(ew * i0); wd1i = (DLReal) sin(ew * i0); wd3i = 4 * wd1i * wd1r; wd3r = wd1r - wd3i * wd1i; wd3i = wd1i - wd3i * wd1r; wk1r = w1r * wd1r - w1i * wd1i; wk1i = w1r * wd1i + w1i * wd1r; wk3i = 4 * wk1i * wk1r; wk3r = wk1r - wk3i * wk1i; wk3i = wk1i - wk3i * wk1r; i = i0; } wd1r = WR5000; j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] + a[j2 - 2]; x0i = a[j0 - 1] + a[j2 - 1]; x1r = a[j0 - 2] - a[j2 - 2]; x1i = a[j0 - 1] - a[j2 - 1]; x2r = a[j1 - 2] + a[j3 - 2]; x2i = a[j1 - 1] + a[j3 - 1]; x3r = a[j1 - 2] - a[j3 - 2]; x3i = a[j1 - 1] - a[j3 - 1]; a[j0 - 2] = x0r + x2r; a[j0 - 1] = x0i + x2i; a[j1 - 2] = x0r - x2r; a[j1 - 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 - 2] = wk1r * x0r - wk1i * x0i; a[j2 - 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 - 2] = wk3r * x0r + wk3i * x0i; a[j3 - 1] = wk3r * x0i - wk3i * x0r; x0r = a[j0] + a[j2]; x0i = a[j0 + 1] + a[j2 + 1]; x1r = a[j0] - a[j2]; x1i = a[j0 + 1] - a[j2 + 1]; x2r = a[j1] + a[j3]; x2i = a[j1 + 1] + a[j3 + 1]; x3r = a[j1] - a[j3]; x3i = a[j1 + 1] - a[j3 + 1]; a[j0] = x0r + x2r; a[j0 + 1] = x0i + x2i; a[j1] = x0r - x2r; a[j1 + 1] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2] = wd1r * (x0r - x0i); a[j2 + 1] = wd1r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = -wd1r * (x0r + x0i); a[j3 + 1] = -wd1r * (x0i - x0r); x0r = a[j0 + 2] + a[j2 + 2]; x0i = a[j0 + 3] + a[j2 + 3]; x1r = a[j0 + 2] - a[j2 + 2]; x1i = a[j0 + 3] - a[j2 + 3]; x2r = a[j1 + 2] + a[j3 + 2]; x2i = a[j1 + 3] + a[j3 + 3]; x3r = a[j1 + 2] - a[j3 + 2]; x3i = a[j1 + 3] - a[j3 + 3]; a[j0 + 2] = x0r + x2r; a[j0 + 3] = x0i + x2i; a[j1 + 2] = x0r - x2r; a[j1 + 3] = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; a[j2 + 2] = wk1i * x0r - wk1r * x0i; a[j2 + 3] = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3 + 2] = wk3i * x0r + wk3r * x0i; a[j3 + 3] = wk3i * x0i - wk3r * x0r; } void cftmdl2(int n, DLReal *a) { int i, i0, j, j0, j1, j2, j3, m, mh; DLReal ew, w1r, w1i, wn4r, wk1r, wk1i, wk3r, wk3i, wl1r, wl1i, wl3r, wl3i, wd1r, wd1i, wd3r, wd3i, we1r, we1i, we3r, we3i, ss1, ss3; DLReal x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i; mh = n >> 3; m = 2 * mh; wn4r = WR5000; j1 = m; j2 = j1 + m; j3 = j2 + m; x0r = a[0] - a[j2 + 1]; x0i = a[1] + a[j2]; x1r = a[0] + a[j2 + 1]; x1i = a[1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wn4r * (x2r - x2i); y0i = wn4r * (x2i + x2r); a[0] = x0r + y0r; a[1] = x0i + y0i; a[j1] = x0r - y0r; a[j1 + 1] = x0i - y0i; y0r = wn4r * (x3r - x3i); y0i = wn4r * (x3i + x3r); a[j2] = x1r - y0i; a[j2 + 1] = x1i + y0r; a[j3] = x1r + y0i; a[j3 + 1] = x1i - y0r; wl1r = 1; wl1i = 0; wl3r = 1; wl3i = 0; we1r = wn4r; we1i = wn4r; we3r = -wn4r; we3i = -wn4r; ew = M_PI_2 / (2 * m); w1r = (DLReal) cos(2 * ew); w1i = (DLReal) sin(2 * ew); wk1r = w1r; wk1i = w1i; wd1r = wn4r * (w1r - w1i); wd1i = wn4r * (w1i + w1r); ss1 = 2 * w1i; wk3i = 2 * ss1 * wk1r; wk3r = wk1r - wk3i * wk1i; wk3i = wk1i - wk3i * wk1r; ss3 = 2 * wk3i; wd3r = -wn4r * (wk3r - wk3i); wd3i = -wn4r * (wk3i + wk3r); i = 0; for (;;) { i0 = i + 4 * CDFT_LOOP_DIV; if (i0 > mh - 4) { i0 = mh - 4; } for (j = i + 2; j < i0; j += 4) { wl1r -= ss1 * wk1i; wl1i += ss1 * wk1r; wl3r -= ss3 * wk3i; wl3i += ss3 * wk3r; we1r -= ss1 * wd1i; we1i += ss1 * wd1r; we3r -= ss3 * wd3i; we3i += ss3 * wd3r; j1 = j + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j] - a[j2 + 1]; x0i = a[j + 1] + a[j2]; x1r = a[j] + a[j2 + 1]; x1i = a[j + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wd1r * x2r - wd1i * x2i; y2i = wd1r * x2i + wd1i * x2r; a[j] = y0r + y2r; a[j + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wk3r * x1r + wk3i * x1i; y0i = wk3r * x1i - wk3i * x1r; y2r = wd3r * x3r + wd3i * x3i; y2i = wd3r * x3i - wd3i * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; x0r = a[j + 2] - a[j2 + 3]; x0i = a[j + 3] + a[j2 + 2]; x1r = a[j + 2] + a[j2 + 3]; x1i = a[j + 3] - a[j2 + 2]; x2r = a[j1 + 2] - a[j3 + 3]; x2i = a[j1 + 3] + a[j3 + 2]; x3r = a[j1 + 2] + a[j3 + 3]; x3i = a[j1 + 3] - a[j3 + 2]; y0r = wl1r * x0r - wl1i * x0i; y0i = wl1r * x0i + wl1i * x0r; y2r = we1r * x2r - we1i * x2i; y2i = we1r * x2i + we1i * x2r; a[j + 2] = y0r + y2r; a[j + 3] = y0i + y2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i - y2i; y0r = wl3r * x1r + wl3i * x1i; y0i = wl3r * x1i - wl3i * x1r; y2r = we3r * x3r + we3i * x3i; y2i = we3r * x3i - we3i * x3r; a[j2 + 2] = y0r + y2r; a[j2 + 3] = y0i + y2i; a[j3 + 2] = y0r - y2r; a[j3 + 3] = y0i - y2i; j0 = m - j; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wd1i * x0r - wd1r * x0i; y0i = wd1i * x0i + wd1r * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wd3i * x1r + wd3r * x1i; y0i = wd3i * x1i - wd3r * x1r; y2r = wk3i * x3r + wk3r * x3i; y2i = wk3i * x3i - wk3r * x3r; a[j2] = y0r + y2r; a[j2 + 1] = y0i + y2i; a[j3] = y0r - y2r; a[j3 + 1] = y0i - y2i; x0r = a[j0 - 2] - a[j2 - 1]; x0i = a[j0 - 1] + a[j2 - 2]; x1r = a[j0 - 2] + a[j2 - 1]; x1i = a[j0 - 1] - a[j2 - 2]; x2r = a[j1 - 2] - a[j3 - 1]; x2i = a[j1 - 1] + a[j3 - 2]; x3r = a[j1 - 2] + a[j3 - 1]; x3i = a[j1 - 1] - a[j3 - 2]; y0r = we1i * x0r - we1r * x0i; y0i = we1i * x0i + we1r * x0r; y2r = wl1i * x2r - wl1r * x2i; y2i = wl1i * x2i + wl1r * x2r; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i + y2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i - y2i; y0r = we3i * x1r + we3r * x1i; y0i = we3i * x1i - we3r * x1r; y2r = wl3i * x3r + wl3r * x3i; y2i = wl3i * x3i - wl3r * x3r; a[j2 - 2] = y0r + y2r; a[j2 - 1] = y0i + y2i; a[j3 - 2] = y0r - y2r; a[j3 - 1] = y0i - y2i; wk1r -= ss1 * wl1i; wk1i += ss1 * wl1r; wk3r -= ss3 * wl3i; wk3i += ss3 * wl3r; wd1r -= ss1 * we1i; wd1i += ss1 * we1r; wd3r -= ss3 * we3i; wd3i += ss3 * we3r; } if (i0 == mh - 4) { break; } wl1r = (DLReal) cos(ew * i0); wl1i = (DLReal) sin(ew * i0); wl3i = 4 * wl1i * wl1r; wl3r = wl1r - wl3i * wl1i; wl3i = wl1i - wl3i * wl1r; we1r = wn4r * (wl1r - wl1i); we1i = wn4r * (wl1i + wl1r); we3r = -wn4r * (wl3r - wl3i); we3i = -wn4r * (wl3i + wl3r); wk1r = w1r * wl1r - w1i * wl1i; wk1i = w1r * wl1i + w1i * wl1r; wk3i = 4 * wk1i * wk1r; wk3r = wk1r - wk3i * wk1i; wk3i = wk1i - wk3i * wk1r; wd1r = wn4r * (wk1r - wk1i); wd1i = wn4r * (wk1i + wk1r); wd3r = -wn4r * (wk3r - wk3i); wd3i = -wn4r * (wk3i + wk3r); i = i0; } wl1r = WR2500; wl1i = WI2500; j0 = mh; j1 = j0 + m; j2 = j1 + m; j3 = j2 + m; x0r = a[j0 - 2] - a[j2 - 1]; x0i = a[j0 - 1] + a[j2 - 2]; x1r = a[j0 - 2] + a[j2 - 1]; x1i = a[j0 - 1] - a[j2 - 2]; x2r = a[j1 - 2] - a[j3 - 1]; x2i = a[j1 - 1] + a[j3 - 2]; x3r = a[j1 - 2] + a[j3 - 1]; x3i = a[j1 - 1] - a[j3 - 2]; y0r = wk1r * x0r - wk1i * x0i; y0i = wk1r * x0i + wk1i * x0r; y2r = wd1r * x2r - wd1i * x2i; y2i = wd1r * x2i + wd1i * x2r; a[j0 - 2] = y0r + y2r; a[j0 - 1] = y0i + y2i; a[j1 - 2] = y0r - y2r; a[j1 - 1] = y0i - y2i; y0r = wk3r * x1r + wk3i * x1i; y0i = wk3r * x1i - wk3i * x1r; y2r = wd3r * x3r + wd3i * x3i; y2i = wd3r * x3i - wd3i * x3r; a[j2 - 2] = y0r + y2r; a[j2 - 1] = y0i + y2i; a[j3 - 2] = y0r - y2r; a[j3 - 1] = y0i - y2i; x0r = a[j0] - a[j2 + 1]; x0i = a[j0 + 1] + a[j2]; x1r = a[j0] + a[j2 + 1]; x1i = a[j0 + 1] - a[j2]; x2r = a[j1] - a[j3 + 1]; x2i = a[j1 + 1] + a[j3]; x3r = a[j1] + a[j3 + 1]; x3i = a[j1 + 1] - a[j3]; y0r = wl1r * x0r - wl1i * x0i; y0i = wl1r * x0i + wl1i * x0r; y2r = wl1i * x2r - wl1r * x2i; y2i = wl1i * x2i + wl1r * x2r; a[j0] = y0r + y2r; a[j0 + 1] = y0i + y2i; a[j1] = y0r - y2r; a[j1 + 1] = y0i - y2i; y0r = wl1i * x1r - wl1r * x1i; y0i = wl1i * x1i + wl1r * x1r; y2r = wl1r * x3r - wl1i * x3i; y2i = wl1r * x3i + wl1i * x3r; a[j2] = y0r - y2r; a[j2 + 1] = y0i - y2i; a[j3] = y0r + y2r; a[j3 + 1] = y0i + y2i; x0r = a[j0 + 2] - a[j2 + 3]; x0i = a[j0 + 3] + a[j2 + 2]; x1r = a[j0 + 2] + a[j2 + 3]; x1i = a[j0 + 3] - a[j2 + 2]; x2r = a[j1 + 2] - a[j3 + 3]; x2i = a[j1 + 3] + a[j3 + 2]; x3r = a[j1 + 2] + a[j3 + 3]; x3i = a[j1 + 3] - a[j3 + 2]; y0r = wd1i * x0r - wd1r * x0i; y0i = wd1i * x0i + wd1r * x0r; y2r = wk1i * x2r - wk1r * x2i; y2i = wk1i * x2i + wk1r * x2r; a[j0 + 2] = y0r + y2r; a[j0 + 3] = y0i + y2i; a[j1 + 2] = y0r - y2r; a[j1 + 3] = y0i - y2i; y0r = wd3i * x1r + wd3r * x1i; y0i = wd3i * x1i - wd3r * x1r; y2r = wk3i * x3r + wk3r * x3i; y2i = wk3i * x3i - wk3r * x3r; a[j2 + 2] = y0r + y2r; a[j2 + 3] = y0i + y2i; a[j3 + 2] = y0r - y2r; a[j3 + 3] = y0i - y2i; } void cftfx41(int n, DLReal *a) { void cftf161(DLReal *a); void cftf162(DLReal *a); void cftf081(DLReal *a); void cftf082(DLReal *a); if (n == 128) { cftf161(a); cftf162(&a[32]); cftf161(&a[64]); cftf161(&a[96]); } else { cftf081(a); cftf082(&a[16]); cftf081(&a[32]); cftf081(&a[48]); } } void cftf161(DLReal *a) { DLReal wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = WR5000; wk1r = WR2500; wk1i = WI2500; x0r = a[0] + a[16]; x0i = a[1] + a[17]; x1r = a[0] - a[16]; x1i = a[1] - a[17]; x2r = a[8] + a[24]; x2i = a[9] + a[25]; x3r = a[8] - a[24]; x3i = a[9] - a[25]; y0r = x0r + x2r; y0i = x0i + x2i; y4r = x0r - x2r; y4i = x0i - x2i; y8r = x1r - x3i; y8i = x1i + x3r; y12r = x1r + x3i; y12i = x1i - x3r; x0r = a[2] + a[18]; x0i = a[3] + a[19]; x1r = a[2] - a[18]; x1i = a[3] - a[19]; x2r = a[10] + a[26]; x2i = a[11] + a[27]; x3r = a[10] - a[26]; x3i = a[11] - a[27]; y1r = x0r + x2r; y1i = x0i + x2i; y5r = x0r - x2r; y5i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y9r = wk1r * x0r - wk1i * x0i; y9i = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y13r = wk1i * x0r - wk1r * x0i; y13i = wk1i * x0i + wk1r * x0r; x0r = a[4] + a[20]; x0i = a[5] + a[21]; x1r = a[4] - a[20]; x1i = a[5] - a[21]; x2r = a[12] + a[28]; x2i = a[13] + a[29]; x3r = a[12] - a[28]; x3i = a[13] - a[29]; y2r = x0r + x2r; y2i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y10r = wn4r * (x0r - x0i); y10i = wn4r * (x0i + x0r); x0r = x1r + x3i; x0i = x1i - x3r; y14r = wn4r * (x0r + x0i); y14i = wn4r * (x0i - x0r); x0r = a[6] + a[22]; x0i = a[7] + a[23]; x1r = a[6] - a[22]; x1i = a[7] - a[23]; x2r = a[14] + a[30]; x2i = a[15] + a[31]; x3r = a[14] - a[30]; x3i = a[15] - a[31]; y3r = x0r + x2r; y3i = x0i + x2i; y7r = x0r - x2r; y7i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; y11r = wk1i * x0r - wk1r * x0i; y11i = wk1i * x0i + wk1r * x0r; x0r = x1r + x3i; x0i = x1i - x3r; y15r = wk1r * x0r - wk1i * x0i; y15i = wk1r * x0i + wk1i * x0r; x0r = y12r - y14r; x0i = y12i - y14i; x1r = y12r + y14r; x1i = y12i + y14i; x2r = y13r - y15r; x2i = y13i - y15i; x3r = y13r + y15r; x3i = y13i + y15i; a[24] = x0r + x2r; a[25] = x0i + x2i; a[26] = x0r - x2r; a[27] = x0i - x2i; a[28] = x1r - x3i; a[29] = x1i + x3r; a[30] = x1r + x3i; a[31] = x1i - x3r; x0r = y8r + y10r; x0i = y8i + y10i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; x3r = y9r - y11r; x3i = y9i - y11i; a[16] = x0r + x2r; a[17] = x0i + x2i; a[18] = x0r - x2r; a[19] = x0i - x2i; a[20] = x1r - x3i; a[21] = x1i + x3r; a[22] = x1r + x3i; a[23] = x1i - x3r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); x0r = y5r + y7i; x0i = y5i - y7r; x3r = wn4r * (x0r - x0i); x3i = wn4r * (x0i + x0r); x0r = y4r - y6i; x0i = y4i + y6r; x1r = y4r + y6i; x1i = y4i - y6r; a[8] = x0r + x2r; a[9] = x0i + x2i; a[10] = x0r - x2r; a[11] = x0i - x2i; a[12] = x1r - x3i; a[13] = x1i + x3r; a[14] = x1r + x3i; a[15] = x1i - x3r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r + y3r; x2i = y1i + y3i; x3r = y1r - y3r; x3i = y1i - y3i; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x0r - x2r; a[3] = x0i - x2i; a[4] = x1r - x3i; a[5] = x1i + x3r; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftf162(DLReal *a) { DLReal wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; wn4r = WR5000; wk1r = WR1250; wk1i = WI1250; wk2r = WR2500; wk2i = WI2500; wk3r = WR3750; wk3i = WI3750; x1r = a[0] - a[17]; x1i = a[1] + a[16]; x0r = a[8] - a[25]; x0i = a[9] + a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y0r = x1r + x2r; y0i = x1i + x2i; y4r = x1r - x2r; y4i = x1i - x2i; x1r = a[0] + a[17]; x1i = a[1] - a[16]; x0r = a[8] + a[25]; x0i = a[9] - a[24]; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); y8r = x1r - x2i; y8i = x1i + x2r; y12r = x1r + x2i; y12i = x1i - x2r; x0r = a[2] - a[19]; x0i = a[3] + a[18]; x1r = wk1r * x0r - wk1i * x0i; x1i = wk1r * x0i + wk1i * x0r; x0r = a[10] - a[27]; x0i = a[11] + a[26]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y1r = x1r + x2r; y1i = x1i + x2i; y5r = x1r - x2r; y5i = x1i - x2i; x0r = a[2] + a[19]; x0i = a[3] - a[18]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[10] + a[27]; x0i = a[11] - a[26]; x2r = wk1r * x0r + wk1i * x0i; x2i = wk1r * x0i - wk1i * x0r; y9r = x1r - x2r; y9i = x1i - x2i; y13r = x1r + x2r; y13i = x1i + x2i; x0r = a[4] - a[21]; x0i = a[5] + a[20]; x1r = wk2r * x0r - wk2i * x0i; x1i = wk2r * x0i + wk2i * x0r; x0r = a[12] - a[29]; x0i = a[13] + a[28]; x2r = wk2i * x0r - wk2r * x0i; x2i = wk2i * x0i + wk2r * x0r; y2r = x1r + x2r; y2i = x1i + x2i; y6r = x1r - x2r; y6i = x1i - x2i; x0r = a[4] + a[21]; x0i = a[5] - a[20]; x1r = wk2i * x0r - wk2r * x0i; x1i = wk2i * x0i + wk2r * x0r; x0r = a[12] + a[29]; x0i = a[13] - a[28]; x2r = wk2r * x0r - wk2i * x0i; x2i = wk2r * x0i + wk2i * x0r; y10r = x1r - x2r; y10i = x1i - x2i; y14r = x1r + x2r; y14i = x1i + x2i; x0r = a[6] - a[23]; x0i = a[7] + a[22]; x1r = wk3r * x0r - wk3i * x0i; x1i = wk3r * x0i + wk3i * x0r; x0r = a[14] - a[31]; x0i = a[15] + a[30]; x2r = wk1i * x0r - wk1r * x0i; x2i = wk1i * x0i + wk1r * x0r; y3r = x1r + x2r; y3i = x1i + x2i; y7r = x1r - x2r; y7i = x1i - x2i; x0r = a[6] + a[23]; x0i = a[7] - a[22]; x1r = wk1i * x0r + wk1r * x0i; x1i = wk1i * x0i - wk1r * x0r; x0r = a[14] + a[31]; x0i = a[15] - a[30]; x2r = wk3i * x0r - wk3r * x0i; x2i = wk3i * x0i + wk3r * x0r; y11r = x1r + x2r; y11i = x1i + x2i; y15r = x1r - x2r; y15i = x1i - x2i; x1r = y0r + y2r; x1i = y0i + y2i; x2r = y1r + y3r; x2i = y1i + y3i; a[0] = x1r + x2r; a[1] = x1i + x2i; a[2] = x1r - x2r; a[3] = x1i - x2i; x1r = y0r - y2r; x1i = y0i - y2i; x2r = y1r - y3r; x2i = y1i - y3i; a[4] = x1r - x2i; a[5] = x1i + x2r; a[6] = x1r + x2i; a[7] = x1i - x2r; x1r = y4r - y6i; x1i = y4i + y6r; x0r = y5r - y7i; x0i = y5i + y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[8] = x1r + x2r; a[9] = x1i + x2i; a[10] = x1r - x2r; a[11] = x1i - x2i; x1r = y4r + y6i; x1i = y4i - y6r; x0r = y5r + y7i; x0i = y5i - y7r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[12] = x1r - x2i; a[13] = x1i + x2r; a[14] = x1r + x2i; a[15] = x1i - x2r; x1r = y8r + y10r; x1i = y8i + y10i; x2r = y9r - y11r; x2i = y9i - y11i; a[16] = x1r + x2r; a[17] = x1i + x2i; a[18] = x1r - x2r; a[19] = x1i - x2i; x1r = y8r - y10r; x1i = y8i - y10i; x2r = y9r + y11r; x2i = y9i + y11i; a[20] = x1r - x2i; a[21] = x1i + x2r; a[22] = x1r + x2i; a[23] = x1i - x2r; x1r = y12r - y14i; x1i = y12i + y14r; x0r = y13r + y15i; x0i = y13i - y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[24] = x1r + x2r; a[25] = x1i + x2i; a[26] = x1r - x2r; a[27] = x1i - x2i; x1r = y12r + y14i; x1i = y12i - y14r; x0r = y13r - y15i; x0i = y13i + y15r; x2r = wn4r * (x0r - x0i); x2i = wn4r * (x0i + x0r); a[28] = x1r - x2i; a[29] = x1i + x2r; a[30] = x1r + x2i; a[31] = x1i - x2r; } void cftf081(DLReal *a) { DLReal wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = WR5000; x0r = a[0] + a[8]; x0i = a[1] + a[9]; x1r = a[0] - a[8]; x1i = a[1] - a[9]; x2r = a[4] + a[12]; x2i = a[5] + a[13]; x3r = a[4] - a[12]; x3i = a[5] - a[13]; y0r = x0r + x2r; y0i = x0i + x2i; y2r = x0r - x2r; y2i = x0i - x2i; y1r = x1r - x3i; y1i = x1i + x3r; y3r = x1r + x3i; y3i = x1i - x3r; x0r = a[2] + a[10]; x0i = a[3] + a[11]; x1r = a[2] - a[10]; x1i = a[3] - a[11]; x2r = a[6] + a[14]; x2i = a[7] + a[15]; x3r = a[6] - a[14]; x3i = a[7] - a[15]; y4r = x0r + x2r; y4i = x0i + x2i; y6r = x0r - x2r; y6i = x0i - x2i; x0r = x1r - x3i; x0i = x1i + x3r; x2r = x1r + x3i; x2i = x1i - x3r; y5r = wn4r * (x0r - x0i); y5i = wn4r * (x0r + x0i); y7r = wn4r * (x2r - x2i); y7i = wn4r * (x2r + x2i); a[8] = y1r + y5r; a[9] = y1i + y5i; a[10] = y1r - y5r; a[11] = y1i - y5i; a[12] = y3r - y7i; a[13] = y3i + y7r; a[14] = y3r + y7i; a[15] = y3i - y7r; a[0] = y0r + y4r; a[1] = y0i + y4i; a[2] = y0r - y4r; a[3] = y0i - y4i; a[4] = y2r - y6i; a[5] = y2i + y6r; a[6] = y2r + y6i; a[7] = y2i - y6r; } void cftf082(DLReal *a) { DLReal wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; wn4r = WR5000; wk1r = WR2500; wk1i = WI2500; y0r = a[0] - a[9]; y0i = a[1] + a[8]; y1r = a[0] + a[9]; y1i = a[1] - a[8]; x0r = a[4] - a[13]; x0i = a[5] + a[12]; y2r = wn4r * (x0r - x0i); y2i = wn4r * (x0i + x0r); x0r = a[4] + a[13]; x0i = a[5] - a[12]; y3r = wn4r * (x0r - x0i); y3i = wn4r * (x0i + x0r); x0r = a[2] - a[11]; x0i = a[3] + a[10]; y4r = wk1r * x0r - wk1i * x0i; y4i = wk1r * x0i + wk1i * x0r; x0r = a[2] + a[11]; x0i = a[3] - a[10]; y5r = wk1i * x0r - wk1r * x0i; y5i = wk1i * x0i + wk1r * x0r; x0r = a[6] - a[15]; x0i = a[7] + a[14]; y6r = wk1i * x0r - wk1r * x0i; y6i = wk1i * x0i + wk1r * x0r; x0r = a[6] + a[15]; x0i = a[7] - a[14]; y7r = wk1r * x0r - wk1i * x0i; y7i = wk1r * x0i + wk1i * x0r; x0r = y0r + y2r; x0i = y0i + y2i; x1r = y4r + y6r; x1i = y4i + y6i; a[0] = x0r + x1r; a[1] = x0i + x1i; a[2] = x0r - x1r; a[3] = x0i - x1i; x0r = y0r - y2r; x0i = y0i - y2i; x1r = y4r - y6r; x1i = y4i - y6i; a[4] = x0r - x1i; a[5] = x0i + x1r; a[6] = x0r + x1i; a[7] = x0i - x1r; x0r = y1r - y3i; x0i = y1i + y3r; x1r = y5r - y7r; x1i = y5i - y7i; a[8] = x0r + x1r; a[9] = x0i + x1i; a[10] = x0r - x1r; a[11] = x0i - x1i; x0r = y1r + y3i; x0i = y1i - y3r; x1r = y5r + y7r; x1i = y5i + y7i; a[12] = x0r - x1i; a[13] = x0i + x1r; a[14] = x0r + x1i; a[15] = x0i - x1r; } void cftf040(DLReal *a) { DLReal x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r - x3i; a[3] = x1i + x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r + x3i; a[7] = x1i - x3r; } void cftb040(DLReal *a) { DLReal x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; x0r = a[0] + a[4]; x0i = a[1] + a[5]; x1r = a[0] - a[4]; x1i = a[1] - a[5]; x2r = a[2] + a[6]; x2i = a[3] + a[7]; x3r = a[2] - a[6]; x3i = a[3] - a[7]; a[0] = x0r + x2r; a[1] = x0i + x2i; a[2] = x1r + x3i; a[3] = x1i - x3r; a[4] = x0r - x2r; a[5] = x0i - x2i; a[6] = x1r - x3i; a[7] = x1i + x3r; } void cftx020(DLReal *a) { DLReal x0r, x0i; x0r = a[0] - a[2]; x0i = a[1] - a[3]; a[0] += a[2]; a[1] += a[3]; a[2] = x0r; a[3] = x0i; } void rftfsub(int n, DLReal *a) { int i, i0, j, k; DLReal ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; ec = 2 * M_PI_2 / n; wkr = 0; wki = 0; wdi = (DLReal) cos(ec); wdr = (DLReal) sin(ec); wdi *= wdr; wdr *= wdr; w1r = 1 - 2 * wdr; w1i = 2 * wdi; ss = 2 * w1i; i = n >> 1; for (;;) { i0 = i - 4 * RDFT_LOOP_DIV; if (i0 < 4) { i0 = 4; } for (j = i - 4; j >= i0; j -= 4) { k = n - j; xr = a[j + 2] - a[k - 2]; xi = a[j + 3] + a[k - 1]; yr = wdr * xr - wdi * xi; yi = wdr * xi + wdi * xr; a[j + 2] -= yr; a[j + 3] -= yi; a[k - 2] += yr; a[k - 1] -= yi; wkr += ss * wdi; wki += ss * (((DLReal) 0.5) - wdr); xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; wdr += ss * wki; wdi += ss * (((DLReal) 0.5) - wkr); } if (i0 == 4) { break; } wkr = ((DLReal) 0.5) * (DLReal) sin(ec * i0); wki = ((DLReal) 0.5) * (DLReal) cos(ec * i0); wdr = ((DLReal) 0.5) - (wkr * w1r - wki * w1i); wdi = wkr * w1i + wki * w1r; wkr = ((DLReal) 0.5) - wkr; i = i0; } xr = a[2] - a[n - 2]; xi = a[3] + a[n - 1]; yr = wdr * xr - wdi * xi; yi = wdr * xi + wdi * xr; a[2] -= yr; a[3] -= yi; a[n - 2] += yr; a[n - 1] -= yi; } void rftbsub(int n, DLReal *a) { int i, i0, j, k; DLReal ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; ec = 2 * M_PI_2 / n; wkr = 0; wki = 0; wdi = (DLReal) cos(ec); wdr = (DLReal) sin(ec); wdi *= wdr; wdr *= wdr; w1r = 1 - 2 * wdr; w1i = 2 * wdi; ss = 2 * w1i; i = n >> 1; for (;;) { i0 = i - 4 * RDFT_LOOP_DIV; if (i0 < 4) { i0 = 4; } for (j = i - 4; j >= i0; j -= 4) { k = n - j; xr = a[j + 2] - a[k - 2]; xi = a[j + 3] + a[k - 1]; yr = wdr * xr + wdi * xi; yi = wdr * xi - wdi * xr; a[j + 2] -= yr; a[j + 3] -= yi; a[k - 2] += yr; a[k - 1] -= yi; wkr += ss * wdi; wki += ss * (((DLReal) 0.5) - wdr); xr = a[j] - a[k]; xi = a[j + 1] + a[k + 1]; yr = wkr * xr + wki * xi; yi = wkr * xi - wki * xr; a[j] -= yr; a[j + 1] -= yi; a[k] += yr; a[k + 1] -= yi; wdr += ss * wki; wdi += ss * (((DLReal) 0.5) - wkr); } if (i0 == 4) { break; } wkr = ((DLReal) 0.5) * (DLReal) sin(ec * i0); wki = ((DLReal) 0.5) * (DLReal) cos(ec * i0); wdr = ((DLReal) 0.5) - (wkr * w1r - wki * w1i); wdi = wkr * w1i + wki * w1r; wkr = ((DLReal) 0.5) - wkr; i = i0; } xr = a[2] - a[n - 2]; xi = a[3] + a[n - 1]; yr = wdr * xr + wdi * xi; yi = wdr * xi - wdi * xr; a[2] -= yr; a[3] -= yi; a[n - 2] += yr; a[n - 1] -= yi; } void dctsub(int n, DLReal *a) { int i, i0, j, k, m; DLReal ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; ec = M_PI_2 / n; wkr = 0.5; wki = 0.5; w1r = (DLReal) cos(ec); w1i = (DLReal) sin(ec); wdr = ((DLReal) 0.5) * (w1r - w1i); wdi = ((DLReal) 0.5) * (w1r + w1i); ss = 2 * w1i; m = n >> 1; i = 0; for (;;) { i0 = i + 2 * DCST_LOOP_DIV; if (i0 > m - 2) { i0 = m - 2; } for (j = i + 2; j <= i0; j += 2) { k = n - j; xr = wdi * a[j - 1] - wdr * a[k + 1]; xi = wdr * a[j - 1] + wdi * a[k + 1]; wkr -= ss * wdi; wki += ss * wdr; yr = wki * a[j] - wkr * a[k]; yi = wkr * a[j] + wki * a[k]; wdr -= ss * wki; wdi += ss * wkr; a[k + 1] = xr; a[k] = yr; a[j - 1] = xi; a[j] = yi; } if (i0 == m - 2) { break; } wdr = (DLReal) cos(ec * i0); wdi = (DLReal) sin(ec * i0); wkr = ((DLReal) 0.5) * (wdr - wdi); wki = ((DLReal) 0.5) * (wdr + wdi); wdr = wkr * w1r - wki * w1i; wdi = wkr * w1i + wki * w1r; i = i0; } xr = wdi * a[m - 1] - wdr * a[m + 1]; a[m - 1] = wdr * a[m - 1] + wdi * a[m + 1]; a[m + 1] = xr; a[m] *= WR5000; } void dstsub(int n, DLReal *a) { int i, i0, j, k, m; DLReal ec, w1r, w1i, wkr, wki, wdr, wdi, ss, xr, xi, yr, yi; ec = M_PI_2 / n; wkr = ((DLReal) 0.5); wki = ((DLReal) 0.5); w1r = (DLReal) cos(ec); w1i = (DLReal) sin(ec); wdr = ((DLReal) 0.5) * (w1r - w1i); wdi = ((DLReal) 0.5) * (w1r + w1i); ss = 2 * w1i; m = n >> 1; i = 0; for (;;) { i0 = i + 2 * DCST_LOOP_DIV; if (i0 > m - 2) { i0 = m - 2; } for (j = i + 2; j <= i0; j += 2) { k = n - j; xr = wdi * a[k + 1] - wdr * a[j - 1]; xi = wdr * a[k + 1] + wdi * a[j - 1]; wkr -= ss * wdi; wki += ss * wdr; yr = wki * a[k] - wkr * a[j]; yi = wkr * a[k] + wki * a[j]; wdr -= ss * wki; wdi += ss * wkr; a[j - 1] = xr; a[j] = yr; a[k + 1] = xi; a[k] = yi; } if (i0 == m - 2) { break; } wdr = (DLReal) cos(ec * i0); wdi = (DLReal) sin(ec * i0); wkr = ((DLReal) 0.5) * (wdr - wdi); wki = ((DLReal) 0.5) * (wdr + wdi); wdr = wkr * w1r - wki * w1i; wdi = wkr * w1i + wki * w1r; i = i0; } xr = wdi * a[m + 1] - wdr * a[m - 1]; a[m + 1] = wdr * a[m + 1] + wdi * a[m - 1]; a[m - 1] = xr; a[m] *= WR5000; } void dctsub4(int n, DLReal *a) { int m; DLReal wki, wdr, wdi, xr; wki = WR5000; m = n >> 1; if (m == 2) { wdr = wki * WI2500; wdi = wki * WR2500; xr = wdi * a[1] - wdr * a[3]; a[1] = wdr * a[1] + wdi * a[3]; a[3] = xr; } a[m] *= wki; } void dstsub4(int n, DLReal *a) { int m; DLReal wki, wdr, wdi, xr; wki = WR5000; m = n >> 1; if (m == 2) { wdr = wki * WI2500; wdi = wki * WR2500; xr = wdi * a[3] - wdr * a[1]; a[3] = wdr * a[3] + wdi * a[1]; a[1] = xr; } a[m] *= wki; } drc-3.2.2/source/drc.cpp0000644000076400001450000021464413165105032014034 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2017 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@neomerica.it This program uses 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. ****************************************************************************/ /* Main file */ /* Inclusioni */ #include "drc.h" #include "dsplib.h" #include "dspwind.h" #include "bwprefilt.h" #include "slprefilt.h" #include "baselib.h" #include "level.h" #include "cfgparse.h" #include "convol.h" #include "hd.h" #include "toeplitz.h" #include "fir.h" #include "kirkebyfd.h" #include "drccfg.h" #include "cmdline.h" #include "spline.h" #include "psychoacoustic.h" #include #include #include #include #include /* Versione corrente */ #define DRCVersion "3.2.2" #define DRCCopyright "2002-2017" /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Header iniziale programma */ void ShowDRCHeader(void) { sputs("\nDRC " DRCVersion ": Digital Room Correction"); sputs("Copyright (C) " DRCCopyright " Denis Sbragion"); #ifdef UseDouble sputs("\nCompiled with double precision arithmetic."); #else sputs("\nCompiled with single precision arithmetic."); #endif #if defined(UseGSLFft) && defined(UseOouraFft) sputs("Using the GNU Scientific Library and Ooura FFT routines."); #else #ifdef UseGSLFft sputs("Using the GNU Scientific Library FFT routines."); #else #ifdef UseOouraFft sputs("Using the Ooura FFT routines."); #else sputs("Using the builtin FFT routines."); #endif #endif #endif sputs("\nThis program may be freely redistributed under the terms of"); sputs("the GNU GPL and is provided to you as is, without any warranty"); sputs("of any kind. Please read the file \"COPYING\" for details."); } /* Descrizione uso programma */ void ShowDRCUsage(void) { sputs("Usage: DRC [--help] [Options] DRCFile"); sputs("\nParameters:\n"); sputs(" --help : show the full options list (long)"); sputs(" Options: parameters overwriting options"); sputs(" DRCFile: name of DRC configuration file\n"); sputs(" Refer to the manual and samples for options"); sputs(" details and file format\n"); } /* Main procedure */ int main(int argc, char * argv[]) { /* Segnale in ingresso */ DLReal * OInSig = NULL; DLReal * InSig; /* Punto iniziale e finale lettura da file */ int PSStart; int PSEnd; /* Componenti minimum phase e excess phase del segnale */ DLReal * MPSig; DLReal * EPSig; /* Punto iniziale e dimenione finestrature */ int WStart1; int WLen1; int WStart2; int WLen2; int WStart3 = 0; int WLen3 = 0; /* Array correzione microfono */ DLReal * MCFilterFreqs; DLReal * MCFilterM; DLReal * MCFilterP; DLReal * MCFilter = NULL; DLReal * MCOutSig; int MCOutSigStart = 0; int MCOutSigLen; int MCMPFLen; /* Componenti MP e EP prefiltrate */ DLReal * MPPFSig; int MPPFSigLen; DLReal * EPPFSig; int EPPFSigLen; /* Array convoluzione MP/EP */ DLReal * MPEPSig = NULL; int MPEPSigLen; /* Array inversione impulso */ DLReal * PTTConv; int PTTConvLen; int PTTConvStart; int PTTRefLen; DLReal * PTFilter; MKSETFType TFType = MKSETFLinearPhase; /* Array calcolo risposta target psicoacustica*/ DLReal * ISRevSig; DLReal * ISMPEPSig; DLReal * ISRevOut = NULL; int ISSigLen; /* Array troncatura ringing */ DLReal * RTSig; int RTSigLen; /* Array risposta target */ DLReal * PSFilterFreqs; DLReal * PSFilterM; DLReal * PSFilterP; DLReal * PSFilter = NULL; DLReal * PSOutSig; int PSOutSigLen; int PSMPFLen; /* Valore RMS segnale in ingresso */ DLReal SRMSValue; /* Array convoluzione finale */ DLReal * TCSig; int TCSigLen; /* Indici generici */ int I; int J; /* Tipo interpolazione filtri target */ InterpolationType FIType = Linear; /* Tipo funzione di prefiltratura */ SLPPrefilteringType SLPType; BWPPrefilteringType BWPType; /* Gestione parametri recuperati dalla linea di comando */ CmdLineType * OptData; char * DRCFile; /* Salvataggio istante di avvio */ time_t CStart = (time_t) 0; /* I386 Debug only, enables all floating point exceptions traps */ /* int em = 0x372; __asm__ ("fldcw %0" : : "m" (em)); */ /* Messaggio iniziale */ ShowDRCHeader(); /* Empty line */ sputs(""); /* Controllo presenza argomenti */ if (argc < 2) { ShowDRCUsage(); return 0; } /* Salvataggio istante di avvio */ CStart = time(NULL); /* Registra le informazioni command line sulla base della struttura di configurazione */ OptData = RegisterCmdLine(CfgParmsDef); if (OptData == NULL) { sputs("Memory allocation failed."); return 1; } /* Recupera i parametri della command line */ if (GetCmdLine(argc,argv,CfgParmsDef,OptData,&DRCFile) != 0) { sputs("\nCommand line parsing error."); return 1; } /* Verifica se stato richiesto l'help */ if (OptData->ParmSet[OptData->OptCount] == True) { /* Visualizza le opzioni disponibili a linea di comando */ ShowDRCUsage(); sputs("Available options:\n"); ShowCmdLine(CfgParmsDef); /* Dealloca le informazioni parsing command line */ FreeCmdLine(OptData, CfgParmsDef); return 0; } /* Verifica che il nome del file sia presente */ if (DRCFile == NULL) { ShowDRCUsage(); return 1; } /* Segnala l'avvio della procedura */ sputsp("Input configuration file: ",DRCFile); /* Recupera la configurazione */ sputs("Parsing configuration file..."); if (CfgParse(DRCFile,CfgParmsDef,CfgSimple) <= 0) { /* Dealloca le informazioni parsing command line */ FreeCmdLine(OptData, CfgParmsDef); CfgFree(CfgParmsDef); sputs(CfgGetLastErrorDsc()); sputs("Configuration file parsing error."); return 1; } sputs("Parsing completed."); /* Sovrascrive la configurazione base con i parametri a linea di comando. */ sputs("Adding command line options..."); CopyCmdLineParms(OptData,CfgParmsDef); /* Imposta la directory base recupero file */ if (SetupDRCCfgBaseDir(&Cfg,CfgParmsDef,OptData) > 0) { /* Dealloca le informazioni parsing command line */ FreeCmdLine(OptData, CfgParmsDef); CfgFree(CfgParmsDef); sputs("Base configuration setup error."); return 1; } /* Dealloca le informazioni parsing command line */ FreeCmdLine(OptData, CfgParmsDef); /* Controllo validit parametri */ sputs("Configuration parameters check."); if (CheckDRCCfg(&Cfg) != 0) { /* Libera la memoria della struttura di configurazione */ CfgFree(CfgParmsDef); free(DRCFile); return 1; } /* Controlla se stata definita un directory base */ if (Cfg.BCBaseDir != NULL) if (strlen(Cfg.BCBaseDir) > 0) sputsp("Base directory: ",Cfg.BCBaseDir); /*********************************************************************************/ /* Importazione iniziale risposta all'impulso */ /*********************************************************************************/ /* Controlla il tipo ricerca centro impulso */ if (Cfg.BCImpulseCenterMode[0] == 'A') { /* Ricerca il centro impulso */ sputsp("Seeking impulse center on: ", Cfg.BCInFile); Cfg.BCImpulseCenter = FindMaxPcm(Cfg.BCInFile,(IFileType) Cfg.BCInFileType[0]); if (Cfg.BCImpulseCenter < 0) return 1; printf("Impulse center found at sample %i.\n",Cfg.BCImpulseCenter); fflush(stdout); } /* Alloca l'array per il segnale in ingresso */ sputs("Allocating input signal array."); InSig = new DLReal[Cfg.BCInitWindow]; if (InSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Legge il file di ingresso */ sputsp("Reading input signal: ",Cfg.BCInFile); if (ReadSignal(Cfg.BCInFile,InSig,Cfg.BCInitWindow,Cfg.BCImpulseCenter, (IFileType) Cfg.BCInFileType[0],&PSStart,&PSEnd) == False) { sputs("Error reading input signal."); return 1; } sputs("Input signal read."); /* Effettua la prefinestratura del segnale */ if (Cfg.BCPreWindowLen > 0) { sputs("Input signal prewindowing."); /* Verifica che la finestratura sia corretta */ if ((Cfg.BCInitWindow / 2 - Cfg.BCPreWindowLen) < PSStart) sputs("!!Warning: input signal too short for correct signal prewindowing, spurious spikes may be generated."); for (I = 0;I < Cfg.BCInitWindow / 2 - Cfg.BCPreWindowLen;I++) InSig[I] = 0; SpacedBlackmanWindow(&InSig[Cfg.BCInitWindow / 2 - Cfg.BCPreWindowLen],Cfg.BCPreWindowLen,Cfg.BCPreWindowGap,WLeft); } /*********************************************************************************/ /* Compensazione microfono */ /*********************************************************************************/ /* Verifica se abilitata */ if (Cfg.MCFilterType[0] != 'N') { /* Verifica se si devono contare i punti filtro */ if (Cfg.MCNumPoints == 0) { sputsp("Counting mic compensation definition file points: ",Cfg.MCPointsFile); Cfg.MCNumPoints = FLineCount(Cfg.MCPointsFile); printf("Mic compensation definition file points: %d\n",Cfg.MCNumPoints); fflush(stdout); } /* Alloca gli array per la generazione del filtro compensazione */ sputs("Allocating mic compensation filter arrays."); MCFilterFreqs = new DLReal[Cfg.MCNumPoints]; if (MCFilterFreqs == NULL) { sputs("Memory allocation failed."); return 1; } MCFilterM = new DLReal[Cfg.MCNumPoints]; if (MCFilterM == NULL) { sputs("Memory allocation failed."); return 1; } MCFilterP = new DLReal[Cfg.MCNumPoints]; if (MCFilterP == NULL) { sputs("Memory allocation failed."); return 1; } MCOutSigLen = Cfg.MCFilterLen + Cfg.BCInitWindow - 1; MCOutSig = new DLReal[MCOutSigLen]; if (MCOutSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Legge i punti del filtro */ sputsp("Reading mic compensation definition file: ",Cfg.MCPointsFile); if (ReadPoints(Cfg.MCPointsFile,(TFMagType) Cfg.MCMagType[0],MCFilterFreqs, MCFilterM,MCFilterP,Cfg.MCNumPoints,Cfg.BCSampleRate) == False) { sputs("Mic compensation file input failed."); return 1; } /* Effettua l'inversione diretta */ sputs("Mic compensation direct inversion."); for (I = 0;I < Cfg.MCNumPoints;I++) { MCFilterM[I] = ((DRCFloat) 1.0) / MCFilterM[I]; MCFilterP[I] = -MCFilterP[I]; } /* Verifica il tipo di interpolazione */ switch(Cfg.MCInterpolationType[0]) { case 'L': FIType = Linear; break; case 'G': FIType = Logarithmic; break; case 'R': FIType = SplineLinear; break; case 'S': FIType = SplineLogarithmic; break; case 'P': FIType = PCHIPLinear; break; case 'H': FIType = PCHIPLogarithmic; break; } /* Verifica il tipo di filtro da utilizzare */ switch (Cfg.MCFilterType[0]) { case 'L': /* Alloca gli array per il filtro */ sputs("Allocating mic compensation filter arrays."); MCFilter = new DLReal[Cfg.MCFilterLen]; if (MCFilter == NULL) { sputs("Memory allocation failed."); return 1; } for (I = 0; I < Cfg.MCFilterLen; I++) MCFilter[I] = 0; /* Calcola la dimensione richiesta per il calcolo del filtro */ if (Cfg.MCMultExponent >= 0) { /* Calcola la potenza di due superiore a Cfg.MCFilterLen */ for(I = 1;I <= Cfg.MCFilterLen;I <<= 1); I *= 1 << Cfg.MCMultExponent; } else I = Cfg.MCFilterLen; /* Calcola il filtro */ sputs("Mic compensation FIR Filter computation..."); if (GenericFir(MCFilter,Cfg.MCFilterLen, MCFilterFreqs,MCFilterM,MCFilterP,Cfg.MCNumPoints,I,FIType) == False) { sputs("FIR Filter computation failed."); return 1; } /* Effettua la finestratura del filtro */ BlackmanWindow(MCFilter,Cfg.MCFilterLen); break; case 'M': /* Alloca gli array per il filtro */ sputs("Allocating mic compensation filter arrays."); MCMPFLen = 1 + 2 * Cfg.MCFilterLen; MCFilter = new DLReal[MCMPFLen]; if (MCFilter == NULL) { sputs("Memory allocation failed."); return 1; } for (I = 0; I < MCMPFLen; I++) MCFilter[I] = 0; /* Calcola la dimensione richiesta per il calcolo del filtro */ if (Cfg.MCMultExponent >= 0) { /* Calcola la potenza di due superiore a Cfg.MCFilterLen */ for(I = 1;I <= MCMPFLen;I <<= 1); I *= 1 << Cfg.MCMultExponent; } else I = MCMPFLen; /* Calcola il filtro */ sputs("Mic compensation FIR Filter computation..."); if (GenericFir(MCFilter,MCMPFLen, MCFilterFreqs,MCFilterM,MCFilterP,Cfg.MCNumPoints,I,FIType) == False) { sputs("FIR Filter computation failed."); return 1; } /* Alloca gli array per la deconvoluzione omomorfa */ sputs("Allocating homomorphic deconvolution arrays."); MPSig = new DLReal[MCMPFLen]; if (MPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera gli array */ for (I = 0;I < MCMPFLen;I++) MPSig[I] = 0; /* Effettua la deconvoluzione omomorfa*/ sputs("MP mic compensation filter extraction homomorphic deconvolution stage..."); if (CepstrumHD(MCFilter,MPSig,NULL,MCMPFLen, Cfg.MCMultExponent) == False) { sputs("Homomorphic deconvolution failed."); return 1; } /* Effettua la finestratura del filtro a fase minima */ HalfBlackmanWindow(MPSig,Cfg.MCFilterLen,0,WRight); /* Copia il filtro a fase minima nell'array filtro */ for (I = 0;I < Cfg.MCFilterLen;I++) MCFilter[I] = MPSig[I]; /* Dealloca l'array deconvoluzione */ delete[] MPSig; break; } /* Verifica se si deve salvare il filtro psicoacustico */ if (Cfg.MCFilterFile != NULL) { /* Salva la componente MP */ sputsp("Saving mic compensation filter: ",Cfg.MCFilterFile); if (WriteSignal(Cfg.MCFilterFile,MCFilter,Cfg.MCFilterLen, (IFileType) Cfg.MCFilterFileType[0]) == False) { sputs("Mic compensation filter save failed."); return 1; } } /* Convoluzione filtro segnale */ sputs("Mic compensation FIR Filter convolution..."); if (DFftConvolve(InSig,Cfg.BCInitWindow,MCFilter, Cfg.MCFilterLen,MCOutSig) == False) { perror("Convolution failed."); return 1; } /* Deallocazione array */ delete[] MCFilter; delete[] InSig; /* Determina la dimensione della finestra di uscita */ if (Cfg.MCOutWindow > 0) { /* Verifica il tipo di filtro */ switch (Cfg.MCFilterType[0]) { case 'L': /* Determina la finestratura filtro */ MCOutSigStart = (MCOutSigLen - Cfg.MCOutWindow) / 2; MCOutSigLen = Cfg.MCOutWindow; /* Effetua la finestratura filtro */ sputs("Mic compensated signal windowing."); BlackmanWindow(&MCOutSig[MCOutSigStart],MCOutSigLen); break; case 'M': /* Determina la finestratura filtro */ MCOutSigStart = (Cfg.BCInitWindow - Cfg.MCOutWindow) / 2; MCOutSigLen = Cfg.MCOutWindow; /* Effetua la finestratura filtro */ sputs("Mic compensated signal windowing."); BlackmanWindow(&MCOutSig[MCOutSigStart],MCOutSigLen); break; } } else { /* Verifica il tipo di filtro */ switch (Cfg.MCFilterType[0]) { case 'L': /* Determina la finestratura filtro */ MCOutSigStart = 0; PSStart += Cfg.MCFilterLen / 2; PSEnd += Cfg.MCFilterLen / 2; break; case 'M': /* Determina la finestratura filtro */ MCOutSigStart = 0; MCOutSigLen = Cfg.BCInitWindow; break; } } /* Normalizzazione segnale risultante */ if (Cfg.MCNormFactor > 0) { sputs("Mic compensated signal normalization."); if (SigNormalize(&MCOutSig[MCOutSigStart],MCOutSigLen,Cfg.MCNormFactor, (NormType) Cfg.MCNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare il segnale compensato */ if (Cfg.MCOutFile != NULL) { /* Salva il segnale compensato */ sputsp("Saving mic compensated signal: ",Cfg.MCOutFile); if (WriteSignal(Cfg.MCOutFile,&MCOutSig[MCOutSigStart],MCOutSigLen, (IFileType) Cfg.MCOutFileType[0]) == False) { sputs("Mic compensated signal save failed."); return 1; } } /* Deallocazione array */ delete[] MCFilterFreqs; delete[] MCFilterM; delete[] MCFilterP; } else { /* Imposta la lunghezza del segnale */ MCOutSigStart = 0; MCOutSigLen = Cfg.BCInitWindow; MCOutSig = InSig; } /*********************************************************************************/ /* Salvataggio segnale convoluzione di test */ /*********************************************************************************/ /* Verifica se attiva la convoluzione di test */ if (Cfg.TCOutFile != NULL || Cfg.PTType[0] != 'N') { /* Alloca l'array per la convoluzione di test */ sputs("Allocating test convolution signal array."); OInSig = new DLReal[MCOutSigLen]; if (OInSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Copia il segnale in ingresso per la convoluzione finale */ for (I = 0,J = MCOutSigStart;I < MCOutSigLen;I++,J++) OInSig[I] = MCOutSig[J]; } /* Calcola il valore RMS del segnale in ingresso */ SRMSValue = GetRMSLevel(&(MCOutSig[MCOutSigStart]),MCOutSigLen); if (SRMSValue > ((DLReal) 0.0)) printf("Input signal RMS level %f (%f dB).\n",(double) SRMSValue, (double) (20 * log10((double) SRMSValue))); else printf("Input signal RMS level %f (-Inf dB).\n",(double) SRMSValue); fflush(stdout); /*********************************************************************************/ /* Dip limiting preventivo */ /*********************************************************************************/ /* Verifica se si deve effettuare il dip limiting */ if (Cfg.BCDLMinGain > 0) { switch (Cfg.BCDLType[0]) { /* Fase lineare */ case 'L': case 'P': sputs("Input signal linear phase dip limiting..."); if (C1LPDipLimit(&MCOutSig[MCOutSigStart],MCOutSigLen,Cfg.BCDLMinGain,Cfg.BCDLStart, Cfg.BCSampleRate,Cfg.BCDLStartFreq,Cfg.BCDLEndFreq,Cfg.BCDLType[0] == 'P',Cfg.BCDLMultExponent) == False) { sputs("Dip limiting failed."); return 1; } break; /* Fase minima */ case 'M': case 'W': sputs("Input signal minimum phase dip limiting..."); if (C1HMPDipLimit(&MCOutSig[MCOutSigStart],MCOutSigLen,Cfg.BCDLMinGain,Cfg.BCDLStart, Cfg.BCSampleRate,Cfg.BCDLStartFreq,Cfg.BCDLEndFreq,Cfg.BCDLType[0] == 'W',Cfg.BCDLMultExponent) == False) { sputs("Dip limiting failed."); return 1; } break; } } /* Verifica se si deve effettuare rinormalizzazione */ if (Cfg.BCNormFactor > 0) { sputs("Input signal normalization."); if (SigNormalize(&MCOutSig[MCOutSigStart],MCOutSigLen,Cfg.BCNormFactor, (NormType) Cfg.BCNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /*********************************************************************************/ /* Deconvoluzione omomorfa */ /*********************************************************************************/ /* Alloca gli array per la deconvoluzione omomorfa */ sputs("Allocating homomorphic deconvolution arrays."); MPSig = new DLReal[2 * MCOutSigLen]; if (MPSig == NULL) { sputs("Memory allocation failed."); return 1; } EPSig = new DLReal[MCOutSigLen]; if (EPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera gli array */ for (I = 0;I < 2 * MCOutSigLen;I++) MPSig[I] = 0; for (I = 0;I < MCOutSigLen;I++) EPSig[I] = 0; /* Effettua la deconvoluzione omomorfa*/ sputs("Homomorphic deconvolution stage..."); if (CepstrumHD(&MCOutSig[MCOutSigStart],&MPSig[MCOutSigLen / 2 - (1 - (MCOutSigLen % 2))],EPSig, MCOutSigLen,Cfg.HDMultExponent) == False) { sputs("Homomorphic deconvolution failed."); return 1; } /* Verifica se si deve effettuare rinormalizzazione */ if (Cfg.HDMPNormFactor > 0) { sputs("Minimum phase component normalization."); if (SigNormalize(MPSig,MCOutSigLen,Cfg.HDMPNormFactor, (NormType) Cfg.HDMPNormType[0]) == False) { sputs("Normalization failed."); return 1; } } if (Cfg.HDEPNormFactor > 0) { sputs("Excess phase component normalization."); if (SigNormalize(EPSig,MCOutSigLen,Cfg.HDEPNormFactor, (NormType) Cfg.HDEPNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare la componente MP */ if (Cfg.HDMPOutFile != NULL) { /* Salva la componente MP */ sputsp("Saving minimum phase component: ",Cfg.HDMPOutFile); if (WriteSignal(Cfg.HDMPOutFile,MPSig,MCOutSigLen, (IFileType) Cfg.HDMPOutFileType[0]) == False) { sputs("Minimum phase component save failed."); return 1; } } /* Verifica se si deve salvare la componente EP */ if (Cfg.HDEPOutFile != NULL) { /* Salva la componente EP */ sputsp("Saving excess phase component: ",Cfg.HDEPOutFile); if (WriteSignal(Cfg.HDEPOutFile,EPSig,MCOutSigLen, (IFileType) Cfg.HDEPOutFileType[0]) == False) { sputs("Excess phase component save failed."); return 1; } } /* Dealloca il segnale di ingresso */ delete[] MCOutSig; /*********************************************************************************/ /* Prefiltratura componente MP */ /*********************************************************************************/ /* Alloca l'array per il segnale MP prefiltrato */ sputs("Allocating minimum phase component prefiltering array."); MPPFSigLen = Cfg.MPLowerWindow + Cfg.MPFilterLen - 1; MPPFSig = new DLReal[MPPFSigLen]; if (MPPFSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera l'array */ for (I = 0;I < MPPFSigLen;I++) MPPFSig[I] = 0; /* Calcola il punto iniziale finestra */ WStart1 = (MCOutSigLen - Cfg.MPLowerWindow) / 2; /* Verifica il tipo di funzione di prefiltratura */ if (Cfg.MPPrefilterFctn[0] == 'P') { /* Proporzionale */ SLPType = SLPProportional; BWPType = BWPProportional; } else { /* Bilineare */ SLPType = SLPBilinear; BWPType = BWPBilinear; } /* Prefiltratura componente MP */ switch (Cfg.MPPrefilterType[0]) { case 'B': sputs("Minimum phase component band windowing."); /* Verifica che la finestratura sia corretta */ if (((Cfg.BCPreWindowLen == 0) && (WStart1 < PSStart)) || ((WStart1 + Cfg.MPLowerWindow) > PSEnd)) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); BWPreFilt(&MPSig[WStart1],Cfg.MPLowerWindow,Cfg.MPUpperWindow, Cfg.MPFilterLen,Cfg.MPBandSplit,Cfg.MPWindowExponent, Cfg.BCSampleRate,Cfg.MPStartFreq,Cfg.MPEndFreq,Cfg.MPWindowGap, MPPFSig,WFull,BWPType); break; case 'b': sputs("Minimum phase component single side band windowing."); /* Verifica che la finestratura sia corretta */ if ((WStart1 + Cfg.MPLowerWindow) > PSEnd) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); BWPreFilt(&MPSig[WStart1],Cfg.MPLowerWindow,Cfg.MPUpperWindow, Cfg.MPFilterLen,Cfg.MPBandSplit,Cfg.MPWindowExponent, Cfg.BCSampleRate,Cfg.MPStartFreq,Cfg.MPEndFreq,Cfg.MPWindowGap, MPPFSig,WRight,BWPType); break; case 'S': sputs("Minimum phase component sliding lowpass prefiltering."); /* Verifica che la finestratura sia corretta */ if (((Cfg.BCPreWindowLen == 0) && (WStart1 < PSStart)) || ((WStart1 + Cfg.MPLowerWindow) > PSEnd)) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); SLPreFilt(&MPSig[WStart1],Cfg.MPLowerWindow,Cfg.MPUpperWindow, Cfg.MPFilterLen,Cfg.MPBandSplit,Cfg.MPWindowExponent, Cfg.BCSampleRate,Cfg.MPStartFreq,Cfg.MPEndFreq,Cfg.MPWindowGap, Cfg.MPFSharpness,MPPFSig,WFull,SLPType); break; case 's': sputs("Minimum phase component single side sliding lowpass prefiltering."); /* Verifica che la finestratura sia corretta */ if ((WStart1 + Cfg.MPLowerWindow) > PSEnd) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); SLPreFilt(&MPSig[WStart1],Cfg.MPLowerWindow,Cfg.MPUpperWindow, Cfg.MPFilterLen,Cfg.MPBandSplit,Cfg.MPWindowExponent, Cfg.BCSampleRate,Cfg.MPStartFreq,Cfg.MPEndFreq,Cfg.MPWindowGap, Cfg.MPFSharpness,MPPFSig,WRight,SLPType); break; } /* Dealloca la componente MP */ delete[] MPSig; /* Calcola la dimensione per la finestratura finale */ if (Cfg.MPPFFinalWindow > 0) { WStart1 = (MPPFSigLen - Cfg.MPPFFinalWindow) / 2; WLen1 = Cfg.MPPFFinalWindow; } else { WStart1 = 0; WLen1 = MPPFSigLen; } /*********************************************************************************/ /* Dip limiting */ /*********************************************************************************/ /* Verifica se si deve effettuare il dip limiting */ if (Cfg.DLMinGain > 0) { switch (Cfg.DLType[0]) { /* Fase lineare */ case 'L': case 'P': sputs("MP signal linear phase dip limiting..."); if (C1LPDipLimit(&MPPFSig[WStart1],WLen1,Cfg.DLMinGain,Cfg.DLStart, Cfg.BCSampleRate,Cfg.DLStartFreq,Cfg.DLEndFreq,Cfg.DLType[0] == 'P',Cfg.DLMultExponent) == False) { sputs("Dip limiting failed."); return 1; } break; /* Fase minima */ case 'M': case 'W': sputs("MP signal minimum phase dip limiting..."); if (C1HMPDipLimit(&MPPFSig[WStart1],WLen1,Cfg.DLMinGain,Cfg.DLStart, Cfg.BCSampleRate,Cfg.DLStartFreq,Cfg.DLEndFreq,Cfg.DLType[0] == 'W',Cfg.DLMultExponent) == False) { sputs("Dip limiting failed."); return 1; } break; } } /* Verifica se deve essere effettuata la rinormalizzazione MP */ if (Cfg.MPHDRecover[0] == 'Y') { /* Alloca gli array per la deconvoluzione omomorfa */ sputs("Allocating homomorphic deconvolution arrays."); MPSig = new DLReal[2 * WLen1]; if (MPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera gli array */ for (I = 0;I < 2 * WLen1;I++) MPSig[I] = 0; /* Controlla se si deve preservare la componente EP della fase minima */ if (Cfg.MPEPPreserve[0] == 'Y') { MPEPSig = new DLReal[WLen1]; if (MPEPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera gli array */ for (I = 0;I < WLen1;I++) MPEPSig[I] = 0; } else MPEPSig = NULL; /* Effettua la deconvoluzione omomorfa*/ sputs("MP Recover homomorphic deconvolution stage..."); if (CepstrumHD(&MPPFSig[WStart1],&MPSig[WLen1 / 2 - (1 - (WLen1 % 2))],MPEPSig, WLen1,Cfg.MPHDMultExponent) == False) { sputs("Homomorphic deconvolution failed."); return 1; } /* Ricopia la componente MP nell'array originale */ for (I = 0,J = WStart1;I < WLen1;I++,J++) MPPFSig[J] = MPSig[I]; /* Dealloca l'array deconvoluzione */ delete[] MPSig; } /* Verifica se si deve effettuare la finestratura finale */ if (Cfg.MPPFFinalWindow > 0) { sputs("Minimum phase component final windowing."); BlackmanWindow(&MPPFSig[WStart1],WLen1); /* Controlla se si deve preservare la componente EP della fase minima */ if (Cfg.MPHDRecover[0] == 'Y' && Cfg.MPEPPreserve[0] == 'Y') /* Effettua la finestratura della componente EP */ BlackmanWindow(MPEPSig,WLen1); } /* Verifica se si deve effettuare rinormalizzazione */ if (Cfg.MPPFNormFactor > 0) { sputs("Minimum phase component normalization."); if (SigNormalize(&MPPFSig[WStart1],WLen1,Cfg.MPPFNormFactor, (NormType) Cfg.MPPFNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare la componente MP finestrata */ if (Cfg.MPPFOutFile != NULL) { /* Salva la componente MP */ sputsp("Saving minimum phase component: ",Cfg.MPPFOutFile); if (WriteSignal(Cfg.MPPFOutFile,&MPPFSig[WStart1],WLen1, (IFileType) Cfg.MPPFOutFileType[0]) == False) { sputs("Minimum phase component save failed."); return 1; } } /*********************************************************************************/ /* Prefiltratura componente EP */ /*********************************************************************************/ /* Controlla se si deve preservare la componente EP della fase minima */ if (Cfg.MPHDRecover[0] == 'Y' && Cfg.MPEPPreserve[0] == 'Y') { /* Alloca l'array per la convoluzione */ sputs("Allocating minimum phase EP recovering arrays."); MPEPSigLen = MCOutSigLen + WLen1 - 1; EPPFSig = new DLReal[MPEPSigLen]; if (EPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Effettua la convoluzione */ sputs("Minimum phase EP recovering..."); if (DFftConvolve(MPEPSig,WLen1,EPSig,MCOutSigLen,EPPFSig) == False) { sputs("Convolution failed."); return 1; } /* Recupera la componente EP */ for (I = 0,J = WLen1 / 2;I < MCOutSigLen;I++, J++) EPSig[I] = EPPFSig[J]; /* Dealloca l'array temporaneo convoluzione */ delete[] MPEPSig; delete[] EPPFSig; } /* Alloca l'array per il segnale EP prefiltrato */ sputs("Allocating excess phase component prefiltering array."); EPPFSigLen = Cfg.EPLowerWindow + Cfg.EPFilterLen - 1; EPPFSig = new DLReal[EPPFSigLen]; if (EPPFSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera l'array */ for (I = 0;I < EPPFSigLen;I++) EPPFSig[I] = 0; /* Calcola il punto iniziale finestra */ WStart2 = (MCOutSigLen - Cfg.EPLowerWindow) / 2; /* Verifica il tipo di funzione di prefiltratura */ if (Cfg.EPPrefilterFctn[0] == 'P') { /* Proporzionale */ SLPType = SLPProportional; BWPType = BWPProportional; } else { /* Bilineare */ SLPType = SLPBilinear; BWPType = BWPBilinear; } /* Prefiltratura componente EP */ switch (Cfg.EPPrefilterType[0]) { case 'B': sputs("Excess phase component band windowing."); /* Verifica che la finestratura sia corretta */ if (((Cfg.BCPreWindowLen == 0) && (WStart2 < PSStart)) || ((WStart2 + Cfg.EPLowerWindow) > PSEnd)) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); BWPreFilt(&EPSig[WStart2],Cfg.EPLowerWindow,Cfg.EPUpperWindow, Cfg.EPFilterLen,Cfg.EPBandSplit,Cfg.EPWindowExponent, Cfg.BCSampleRate,Cfg.EPStartFreq,Cfg.EPEndFreq,Cfg.EPWindowGap, EPPFSig,WFull,BWPType); break; case 'b': sputs("Excess phase component single side band windowing."); /* Verifica che la finestratura sia corretta */ if ((WStart2 + Cfg.EPLowerWindow) > PSEnd) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); BWPreFilt(&EPSig[WStart2],Cfg.EPLowerWindow,Cfg.EPUpperWindow, Cfg.EPFilterLen,Cfg.EPBandSplit,Cfg.EPWindowExponent, Cfg.BCSampleRate,Cfg.EPStartFreq,Cfg.EPEndFreq,Cfg.EPWindowGap, EPPFSig,WRight,BWPType); break; case 'S': sputs("Excess phase component sliding lowpass prefiltering."); /* Verifica che la finestratura sia corretta */ if (((Cfg.BCPreWindowLen == 0) && (WStart2 < PSStart)) || ((WStart2 + Cfg.EPLowerWindow) > PSEnd)) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); SLPreFilt(&EPSig[WStart2],Cfg.EPLowerWindow,Cfg.EPUpperWindow, Cfg.EPFilterLen,Cfg.EPBandSplit,Cfg.EPWindowExponent, Cfg.BCSampleRate,Cfg.EPStartFreq,Cfg.EPEndFreq,Cfg.EPWindowGap, Cfg.EPFSharpness,EPPFSig,WFull,SLPType); break; case 's': sputs("Excess phase component single side sliding lowpass prefiltering."); /* Verifica che la finestratura sia corretta */ if ((WStart2 + Cfg.EPLowerWindow) > PSEnd) sputs("!!Warning: input signal too short for correct signal prefiltering, spurious spikes may be generated."); SLPreFilt(&EPSig[WStart2],Cfg.EPLowerWindow,Cfg.EPUpperWindow, Cfg.EPFilterLen,Cfg.EPBandSplit,Cfg.EPWindowExponent, Cfg.BCSampleRate,Cfg.EPStartFreq,Cfg.EPEndFreq,Cfg.EPWindowGap, Cfg.EPFSharpness,EPPFSig,WRight,SLPType); break; } /* Dealloca la componente EP */ delete[] EPSig; /* Determina la lunghezza della componente dopo la finestratura */ if (Cfg.EPPFFinalWindow > 0) { WStart2 = (EPPFSigLen - Cfg.EPPFFinalWindow) / 2; WLen2 = Cfg.EPPFFinalWindow; } else { WStart2 = 0; WLen2 = EPPFSigLen; } /* Verifica se si deve effettuare riappianamento */ if (Cfg.EPPFFlatGain > 0) { switch (Cfg.EPPFFlatType[0]) { case 'L': sputs("Excess phase component linear phase flattening..."); LPNormFlat(&EPPFSig[WStart2],WLen2,Cfg.EPPFFlatGain, Cfg.EPPFOGainFactor,Cfg.EPPFFGMultExponent); break; case 'M': sputs("Excess phase component minimum phase flattening..."); CMPNormFlat(&EPPFSig[WStart2],WLen2,Cfg.EPPFFlatGain, Cfg.EPPFOGainFactor,Cfg.EPPFFGMultExponent); break; case 'D': /* Alloca gli array per la deconvoluzione omomorfa */ sputs("Allocating homomorphic deconvolution arrays."); EPSig = new DLReal[WLen2]; if (EPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera gli array per la deconvoluzione omomorfa */ for (I = 0;I < WLen2;I++) EPSig[I] = 0; /* Effettua la deconvoluzione omomorfa*/ sputs("Excess phase component homomorphic deconvolution flattening..."); if (CepstrumHD(&EPPFSig[WStart2],NULL,EPSig, WLen2,Cfg.EPPFFGMultExponent) == False) { sputs("Homomorphic deconvolution failed."); return 1; } /* Copia il risultato nell'array destinazione */ for (I = 0,J = WStart2;I < WLen2;I++,J++) EPPFSig[J] = EPSig[I]; /* Dealloca gli array per la deconvoluzione omomorfa */ delete[] EPSig; break; } } /* Verifica se si deve effettuare la finestratura finale */ if (Cfg.EPPFFinalWindow > 0) { sputs("Excess phase component final windowing."); BlackmanWindow(&EPPFSig[WStart2],WLen2); } /* Verifica se si deve effettuare rinormalizzazione */ if (Cfg.EPPFNormFactor > 0) { sputs("Excess phase component normalization."); if (SigNormalize(&EPPFSig[WStart2],WLen2,Cfg.EPPFNormFactor, (NormType) Cfg.EPPFNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare la componente EP finestrata */ if (Cfg.EPPFOutFile != NULL) { /* Salva la componente MP */ sputsp("Saving excess phase component: ",Cfg.EPPFOutFile); if (WriteSignal(Cfg.EPPFOutFile,&EPPFSig[WStart2],WLen2, (IFileType) Cfg.EPPFOutFileType[0]) == False) { sputs("Excess phase component save failed."); return 1; } } /*********************************************************************************/ /* Combinazione componente MP e EP */ /*********************************************************************************/ /* Controlla se si deve attuare la fase PC */ if (Cfg.ISType[0] == 'L' || Cfg.PCOutFile != NULL) { /* Alloca l'array per la convoluzione MP/EP */ sputs("Allocating MP/EP convolution array."); MPEPSigLen = WLen1 + WLen2 - 1; MPEPSig = new DLReal[MPEPSigLen]; if (MPEPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Convoluzione MP/EP */ sputs("MP/EP Convolution..."); if (DFftConvolve(&MPPFSig[WStart1],WLen1,&EPPFSig[WStart2],WLen2,MPEPSig) == False) { sputs("Convolution failed."); return 1; } /* Dealloca gli array MP/EP finestrati */ if (Cfg.ISType[0] == 'L') { delete[] MPPFSig; delete[] EPPFSig; } /* Finestratura segnale risultante */ if (Cfg.PCOutWindow > 0) { sputs("MP/EP signal windowing."); WStart3 = (MPEPSigLen - Cfg.PCOutWindow) / 2; WLen3 = Cfg.PCOutWindow; BlackmanWindow(&MPEPSig[WStart3],WLen3); } else { WStart3 = 0; WLen3 = MPEPSigLen; } /* Normalizzazione segnale risultante */ if (Cfg.PCNormFactor > 0) { sputs("MP/EP normalization."); if (SigNormalize(&MPEPSig[WStart3],WLen3,Cfg.PCNormFactor, (NormType) Cfg.PCNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare il segnale prefinestrato */ if (Cfg.PCOutFile != NULL) { /* Salva la componente MP */ sputsp("Saving MP/EP signal: ",Cfg.PCOutFile); if (WriteSignal(Cfg.PCOutFile,&MPEPSig[WStart3],WLen3, (IFileType) Cfg.PCOutFileType[0]) == False) { sputs("MP/EP signal save failed."); return 1; } } /* Dealloca gli array */ if (Cfg.ISType[0] != 'L') delete[] MPEPSig; } /*********************************************************************************/ /* Inversione risposta all'impulso */ /*********************************************************************************/ /* Verifica tipo inversione */ switch (Cfg.ISType[0]) { /* Fase lineare con matrice Toeplitz */ case 'L': /* Ricalcola le finestre effettive per l'inversione */ if (Cfg.ISOutWindow > 0) { /* Finestra di inversione predefinita */ ISSigLen = Cfg.ISOutWindow; /* Verifica che il segnale in ingresso sia di lunghezza adeguata */ if (WLen3 > ISSigLen) { /* Ricalcola la lunghezza del segnale in ingresso */ WStart3 += (WLen3 - ISSigLen) / 2; WLen3 = ISSigLen; /* Rifiniestra il segnale per riportarlo alla lunghezza dell'inversione */ BlackmanWindow(&MPEPSig[WStart3],ISSigLen); } } else /* Adotta la finestra precedente */ ISSigLen = WLen3; /* Alloca l'array per l'inversione segnale */ sputs("Allocating delay/reverse array."); ISRevSig = new DLReal[ISSigLen]; if (ISRevSig == NULL) { sputs("Memory allocation failed."); return 1; } for (I = 0;I < ISSigLen;I++) ISRevSig[I] = (DLReal) 0.0; /* Alloca l'array per l'autocorrelazione */ sputs("Allocating autocorrelation array."); ISMPEPSig = new DLReal[ISSigLen]; if (ISMPEPSig == NULL) { sputs("Memory allocation failed."); return 1; } for (I = 0;I < ISSigLen;I++) ISMPEPSig[I] = (DLReal) 0.0; for (I = WStart3,J = (ISSigLen - WLen3) / 2;I < WStart3 + WLen3;I++,J++) ISMPEPSig[J] = MPEPSig[I]; /* Dealloca il segnale composto MP/EP */ delete[] MPEPSig; /* Inversione e ritardo segnale */ sputs("Signal delay/reverse."); for (I = 0,J = ISSigLen - 1;I < ISSigLen;I++,J--) ISRevSig[J] = ISMPEPSig[I]; /* Calcolo autocorrelazione e setup inversione */ sputs("Autocorrelation computation..."); if (AutoCorrelation(ISMPEPSig,ISSigLen) == False) { sputs("Autocorrelation computation failed."); return 1; } for (I = ISSigLen / 2; I < ISSigLen; I++) ISMPEPSig[I] = 0; /* Alloca l'array per l'inversione segnale */ sputs("Allocating inversion array."); ISRevOut = new DLReal[ISSigLen]; if (ISRevOut == NULL) { sputs("Memory allocation failed."); return 1; } /* Effettua l'inversione del segnale */ sputs("Toeplitz least square inversion..."); if (ToeplitzSolve(ISMPEPSig,ISRevSig,ISRevOut,ISSigLen) != 0) { sputs("Inversion failed."); return 1; } /* Dealloca gli array */ delete[] ISRevSig; delete[] ISMPEPSig; /* Reimposta la lunghezza */ WLen3 = ISSigLen; break; /* A fase minima con pre-echo truncation */ case 'T': /* Verifica la dimensione filtro richiesta */ if (Cfg.ISOutWindow > 0) WLen3 = Cfg.ISOutWindow; else WLen3 = WLen1 + WLen2 - 1; /* Alloca l'array per l'inversione segnale */ sputs("Allocating inversion array."); ISRevOut = new DLReal[WLen3]; if (ISRevOut == NULL) { sputs("Memory allocation failed."); return 1; } /* Verifica il tipo di funzione di prefiltratura */ if (Cfg.ISPrefilterFctn[0] == 'P') /* Proporzionale */ SLPType = SLPProportional; else /* Bilineare */ SLPType = SLPBilinear; /* Inversione a fase minima selettiva */ sputs("Pre-echo truncation fast deconvolution..."); if (PETFDInvert(&MPPFSig[WStart1],WLen1,&EPPFSig[WStart2],WLen2,ISRevOut,WLen3, Cfg.ISPETType[0],Cfg.ISPELowerWindow,Cfg.ISPEUpperWindow,Cfg.ISPEStartFreq, Cfg.ISPEEndFreq,Cfg.ISPEFilterLen,Cfg.ISPEFSharpness,Cfg.ISPEBandSplit, Cfg.ISPEWindowExponent,SLPType,Cfg.ISPEOGainFactor,Cfg.BCSampleRate, Cfg.ISSMPMultExponent) == False) { sputs("Inversion failed."); return 1; } /* Dealloca gli array MP/EP finestrati */ delete[] MPPFSig; delete[] EPPFSig; break; } /* Finestratura segnale risultante */ if (Cfg.ISOutWindow > 0) { sputs("Inverted signal windowing."); WStart2 = (WLen3 - Cfg.ISOutWindow) / 2; WLen2 = Cfg.ISOutWindow; BlackmanWindow(&ISRevOut[WStart2],WLen2); } else { WStart2 = 0; WLen2 = WLen3; BlackmanWindow(&ISRevOut[WStart2],WLen2); } /* Normalizzazione segnale risultante */ if (Cfg.ISNormFactor > 0) { sputs("Inverted signal normalization."); if (SigNormalize(&ISRevOut[WStart2],WLen2,Cfg.ISNormFactor, (NormType) Cfg.ISNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare il segnale invertito */ if (Cfg.ISOutFile != NULL) { /* Salva la componente MP */ sputsp("Saving inverted signal: ",Cfg.ISOutFile); if (WriteSignal(Cfg.ISOutFile,&ISRevOut[WStart2],WLen2, (IFileType) Cfg.ISOutFileType[0]) == False) { sputs("Inverted signal save failed."); return 1; } } /*********************************************************************************/ /* Calcolo target psicoacustico */ /*********************************************************************************/ /* Verifica se il target psicoacustico abilitato */ if (Cfg.PTType[0] != 'N') { /* Alloca l'array per la convoluzione filtro e risposta */ sputs("Allocating psychoacoustic target reference convolution array."); PTTConvLen = WLen2 + MCOutSigLen - 1; PTTConv = new DLReal[PTTConvLen]; if (PTTConv == NULL) { sputs("Memory allocation failed."); return 1; } /* Effettua la convoluzione tra filtro e risposta */ sputs("Psychoacoustic target reference convolution..."); if (DFftConvolve(OInSig,MCOutSigLen,ISRevOut,WLen2,PTTConv) == False) { sputs("Convolution failed."); return 1; } /* Effettua la finestratura della convoluzione di riferimento */ PTTRefLen = (PTTConvLen - Cfg.PTReferenceWindow) / 2; for (I = 0;I < PTTRefLen;I++) PTTConv[I] = (DLReal) 0.0; BlackmanWindow(&PTTConv[PTTRefLen],Cfg.PTReferenceWindow); for (I = (PTTRefLen + Cfg.PTReferenceWindow);I < PTTConvLen;I++) PTTConv[I] = (DLReal) 0.0; /* Verifica se si deve effettuare il dip limiting sulla risposta target */ if (Cfg.PTDLMinGain > 0) { switch (Cfg.PTDLType[0]) { /* Fase lineare */ case 'L': case 'P': sputs("Target reference signal linear phase dip limiting..."); if (C1LPDipLimit(&PTTConv[PTTRefLen],Cfg.PTReferenceWindow,Cfg.PTDLMinGain,Cfg.PTDLStart, Cfg.BCSampleRate,Cfg.PTDLStartFreq,Cfg.PTDLEndFreq,Cfg.PTDLType[0] == 'P',Cfg.PTDLMultExponent) == False) { sputs("Dip limiting failed."); return 1; } break; /* Fase minima */ case 'M': case 'W': sputs("Target reference minimum phase dip limiting..."); if (C1HMPDipLimit(&PTTConv[PTTRefLen],Cfg.PTReferenceWindow,Cfg.PTDLMinGain,Cfg.PTDLStart, Cfg.BCSampleRate,Cfg.PTDLStartFreq,Cfg.PTDLEndFreq,Cfg.PTDLType[0] == 'W',Cfg.PTDLMultExponent) == False) { sputs("Dip limiting failed."); return 1; } break; } } /* Alloca l'array per il calcolo del filtro target */ sputs("Allocating psychoacoustic target filter array."); PTFilter = new DLReal[Cfg.PTFilterLen]; if (PTFilter == NULL) { sputs("Memory allocation failed."); return 1; } /* Imposta il tipo filtro target */ switch (Cfg.PTType[0]) { case 'L': TFType = MKSETFLinearPhase; break; case 'M': TFType = MKSETFMinimumPhase; break; } /* Calcola il filtro target psicoacustico */ sputs("Computing psychoacoustic target filter..."); if (P2MKSETargetFilter(&PTTConv[PTTRefLen],Cfg.PTReferenceWindow,Cfg.BCSampleRate, Cfg.PTBandWidth,Cfg.PTPeakDetectionStrength,PTFilter,TFType, Cfg.PTMultExponent,Cfg.PTFilterLen,Cfg.PTDLMinGain,Cfg.PTDLStart, Cfg.BCSampleRate,Cfg.PTDLStartFreq,Cfg.PTDLEndFreq) == False) { sputs("Psychoacoustic target filter computation failed."); return 1; } /* Dealloca l'array per la convoluzione target */ delete[] PTTConv; /* Verifica se si deve salvare il filtro psicoacustico */ if (Cfg.PTFilterFile != NULL) { /* Normalizzazione segnale risultante */ if (Cfg.PTNormFactor > 0) { sputs("Psychoacoustic target filter normalization."); if (SigNormalize(PTFilter,Cfg.PTFilterLen,Cfg.PTNormFactor, (NormType) Cfg.PTNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Salva la componente MP */ sputsp("Saving psychoacoustic target filter: ",Cfg.PTFilterFile); if (WriteSignal(Cfg.PTFilterFile,PTFilter,Cfg.PTFilterLen, (IFileType) Cfg.PTFilterFileType[0]) == False) { sputs("Psychoacoustic target filter save failed."); return 1; } } /* Verifica il tipo di filtro target */ switch (TFType) { case MKSETFLinearPhase: PTTConvStart = 0; PTTConvLen = WLen2 + Cfg.PTFilterLen - 1; break; case MKSETFMinimumPhase: PTTConvStart = Cfg.PTFilterLen - 1; PTTConvLen = WLen2 + 2 * (Cfg.PTFilterLen - 1); break; } /* Alloca l'array per la convoluzione filtro e target */ sputs("Allocating psychoacoustic target correction filter convolution array."); PTTConv = new DLReal[PTTConvLen]; if (PTTConv == NULL) { sputs("Memory allocation failed."); return 1; } for (I = 0;I < PTTConvStart;I++) PTTConv[I] = (DLReal) 0.0; /* Effettua la convoluzione tra filtro e target */ sputs("Psychoacoustic target correction filter convolution..."); if (DFftConvolve(PTFilter,Cfg.PTFilterLen,&ISRevOut[WStart2],WLen2,&PTTConv[PTTConvStart]) == False) { sputs("Convolution failed."); return 1; } /* Dealloca il filtro target */ delete[] PTFilter; /* Finestratura finale filtro risultante */ if (Cfg.PTOutWindow > 0) { sputs("Psychoacoustic target correction filter windowing."); WStart2 = (PTTConvLen - Cfg.PTOutWindow) / 2; WLen2 = Cfg.PTOutWindow; BlackmanWindow(&PTTConv[WStart2],WLen2); } else { WStart2 = 0; WLen2 = PTTConvLen; } /* Normalizzazione segnale risultante */ if (Cfg.PTNormFactor > 0) { sputs("Psychoacoustic target correction filter normalization."); if (SigNormalize(&PTTConv[WStart2],WLen2,Cfg.PTNormFactor, (NormType) Cfg.PTNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare il filtro correzione psicoacustico */ if (Cfg.PTOutFile != NULL) { /* Salva il filtro correzione psicoacustico */ sputsp("Saving psychoacoustic target correction filter: ",Cfg.PTOutFile); if (WriteSignal(Cfg.PTOutFile,&PTTConv[WStart2],WLen2, (IFileType) Cfg.PTOutFileType[0]) == False) { sputs("Psychoacoustic target correction filter save failed."); return 1; } } /* Dealloca e riassegna il filtro inverso */ delete[] ISRevOut; ISRevOut = PTTConv; } /*********************************************************************************/ /* Peak limiting */ /*********************************************************************************/ /* Controlla se si deve effettuare il peak limiting */ if (Cfg.PLMaxGain > 0) { switch (Cfg.PLType[0]) { /* Fase lineare */ case 'L': case 'P': sputs("Linear phase peak limiting..."); if (C1LPPeakLimit(&ISRevOut[WStart2],WLen2,Cfg.PLMaxGain,Cfg.PLStart, Cfg.BCSampleRate,Cfg.PLStartFreq,Cfg.PLEndFreq,Cfg.PLType[0] == 'P',Cfg.PLMultExponent) == False) { sputs("Peak limiting failed."); return 1; } break; /* Fase minima */ case 'M': case 'W': sputs("Minimum phase peak limiting..."); if (C1HMPPeakLimit(&ISRevOut[WStart2],WLen2,Cfg.PLMaxGain,Cfg.PLStart, Cfg.BCSampleRate,Cfg.PLStartFreq,Cfg.PLEndFreq,Cfg.PLType[0] == 'W',Cfg.PLMultExponent) == False) { sputs("Peak limiting failed."); return 1; } break; } } /* Effettua la finestratura finale */ if (Cfg.PLOutWindow > 0) { WStart2 = (WLen2 - Cfg.PLOutWindow) / 2; WLen2 = Cfg.PLOutWindow; sputs("Peak limited signal final windowing."); BlackmanWindow(&ISRevOut[WStart2],WLen2); } /* Normalizzazione segnale risultante */ if (Cfg.PLNormFactor > 0) { sputs("Peak limited signal normalization."); if (SigNormalize(&ISRevOut[WStart2],WLen2,Cfg.PLNormFactor, (NormType) Cfg.PLNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare il segnale limitato */ if (Cfg.PLOutFile != NULL) { /* Salva il segnale limitato*/ sputsp("Saving peak limited signal: ",Cfg.PLOutFile); if (WriteSignal(Cfg.PLOutFile,&ISRevOut[WStart2],WLen2, (IFileType) Cfg.PLOutFileType[0]) == False) { sputs("Peak limited signal save failed."); return 1; } } /*********************************************************************************/ /* Troncatura ringing */ /*********************************************************************************/ /* Controlla se abilitata */ if (Cfg.RTType[0] != 'N') { /* Alloca l'array per la troncatura ringing */ sputs("Allocating ringing truncation array."); RTSigLen = Cfg.RTLowerWindow + Cfg.RTFilterLen - 1; RTSig = new DLReal[RTSigLen]; if (RTSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera l'array */ for (I = 0;I < RTSigLen;I++) RTSig[I] = 0; /* Calcola il punto iniziale finestra */ WStart3 = (WLen2 - Cfg.RTLowerWindow) / 2; /* Verifica il tipo di funzione di prefiltratura */ if (Cfg.RTPrefilterFctn[0] == 'P') { /* Proporzionale */ SLPType = SLPProportional; BWPType = BWPProportional; } else { /* Bilineare */ SLPType = SLPBilinear; BWPType = BWPBilinear; } /* Prefiltratura componente EP */ switch (Cfg.RTType[0]) { case 'B': sputs("Ringing truncation band windowing."); BWPreFilt(&ISRevOut[WStart3],Cfg.RTLowerWindow,Cfg.RTUpperWindow, Cfg.RTFilterLen,Cfg.RTBandSplit,Cfg.RTWindowExponent, Cfg.BCSampleRate,Cfg.RTStartFreq,Cfg.RTEndFreq,Cfg.RTWindowGap, RTSig,WFull,BWPType); break; case 'b': sputs("Ringing truncation single side band windowing."); BWPreFilt(&ISRevOut[WStart3],Cfg.RTLowerWindow,Cfg.RTUpperWindow, Cfg.RTFilterLen,Cfg.RTBandSplit,Cfg.RTWindowExponent, Cfg.BCSampleRate,Cfg.RTStartFreq,Cfg.RTEndFreq,Cfg.RTWindowGap, RTSig,WRight,BWPType); break; case 'S': sputs("Ringing truncation sliding lowpass filtering."); SLPreFilt(&ISRevOut[WStart3],Cfg.RTLowerWindow,Cfg.RTUpperWindow, Cfg.RTFilterLen,Cfg.RTBandSplit,Cfg.RTWindowExponent, Cfg.BCSampleRate,Cfg.RTStartFreq,Cfg.RTEndFreq,Cfg.RTWindowGap, Cfg.RTFSharpness,RTSig,WFull,SLPType); break; case 's': sputs("Ringing truncation single side sliding lowpass filtering."); SLPreFilt(&ISRevOut[WStart3],Cfg.RTLowerWindow,Cfg.RTUpperWindow, Cfg.RTFilterLen,Cfg.RTBandSplit,Cfg.RTWindowExponent, Cfg.BCSampleRate,Cfg.RTStartFreq,Cfg.RTEndFreq,Cfg.RTWindowGap, Cfg.RTFSharpness,RTSig,WRight,SLPType); break; } /* Dealloca il segnale invertito */ delete[] ISRevOut; /* Determina la lunghezza della componente dopo la finestratura */ if (Cfg.RTOutWindow > 0) { WStart2 = (RTSigLen - Cfg.RTOutWindow) / 2; WLen2 = Cfg.RTOutWindow; } else { WStart2 = 0; WLen2 = RTSigLen; } /* Verifica se si deve effettuare la finestratura finale */ if (Cfg.RTOutWindow > 0) { sputs("Ringing truncation final windowing."); BlackmanWindow(&RTSig[WStart2],WLen2); } /* Verifica se si deve effettuare rinormalizzazione */ if (Cfg.RTNormFactor > 0) { sputs("Ringing truncation normalization."); if (SigNormalize(&RTSig[WStart2],WLen2,Cfg.RTNormFactor, (NormType) Cfg.RTNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare la troncatura ringing */ if (Cfg.RTOutFile != NULL) { /* Salva la componente MP */ sputsp("Saving ringing truncation: ",Cfg.RTOutFile); if (WriteSignal(Cfg.RTOutFile,&RTSig[WStart2],WLen2, (IFileType) Cfg.RTOutFileType[0]) == False) { sputs("Ringing truncation save failed."); return 1; } } /* Reimposta il segnale invertito */ ISRevOut = RTSig; } /*********************************************************************************/ /* Applicazione risposta target */ /*********************************************************************************/ /* Verifica se si devono contare i punti filtro */ if (Cfg.PSNumPoints == 0) { sputsp("Counting target response definition file points: ",Cfg.PSPointsFile); Cfg.PSNumPoints = FLineCount(Cfg.PSPointsFile); printf("Target response definition file points: %d\n",Cfg.PSNumPoints); fflush(stdout); } /* Alloca gli array per la generazione della risposta target */ sputs("Allocating target response arrays."); PSFilterFreqs = new DLReal[Cfg.PSNumPoints]; if (PSFilterFreqs == NULL) { sputs("Memory allocation failed."); return 1; } PSFilterM = new DLReal[Cfg.PSNumPoints]; if (PSFilterM == NULL) { sputs("Memory allocation failed."); return 1; } PSFilterP = new DLReal[Cfg.PSNumPoints]; if (PSFilterP == NULL) { sputs("Memory allocation failed."); return 1; } PSOutSigLen = Cfg.PSFilterLen + WLen2 - 1; PSOutSig = new DLReal[PSOutSigLen]; if (PSOutSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Legge i punti del filtro */ sputsp("Reading target response definition file: ",Cfg.PSPointsFile); if (ReadPoints(Cfg.PSPointsFile,(TFMagType) Cfg.PSMagType[0],PSFilterFreqs, PSFilterM,PSFilterP,Cfg.PSNumPoints,Cfg.BCSampleRate) == False) { sputs("Target response point file input failed."); return 1; } /* Verifica il tipo di interpolazione */ switch(Cfg.PSInterpolationType[0]) { case 'L': FIType = Linear; break; case 'G': FIType = Logarithmic; break; case 'R': FIType = SplineLinear; break; case 'S': FIType = SplineLogarithmic; break; case 'P': FIType = PCHIPLinear; break; case 'H': FIType = PCHIPLogarithmic; break; } /* Verifica il tipo di filtro da utilizzare */ switch (Cfg.PSFilterType[0]) { case 'L': /* Alloca gli array per il filtro */ sputs("Allocating target filter arrays."); PSFilter = new DLReal[Cfg.PSFilterLen]; if (PSFilter == NULL) { sputs("Memory allocation failed."); return 1; } for (I = 0; I < Cfg.PSFilterLen; I++) PSFilter[I] = 0; /* Calcola la dimensione richiesta per il calcolo del filtro */ if (Cfg.PSMultExponent >= 0) { /* Calcola la potenza di due superiore a Cfg.PSFilterLen */ for(I = 1;I <= Cfg.PSFilterLen;I <<= 1); I *= 1 << Cfg.PSMultExponent; } else I = Cfg.PSFilterLen; /* Calcola il filtro */ sputs("FIR Filter computation..."); if (GenericFir(PSFilter,Cfg.PSFilterLen, PSFilterFreqs,PSFilterM,PSFilterP,Cfg.PSNumPoints,I,FIType) == False) { sputs("FIR Filter computation failed."); return 1; } /* Effettua la finestratura del filtro */ BlackmanWindow(PSFilter,Cfg.PSFilterLen); break; case 'M': case 'T': /* Alloca gli array per il filtro */ sputs("Allocating target filter arrays."); PSMPFLen = 1 + 2 * Cfg.PSFilterLen; PSFilter = new DLReal[PSMPFLen]; if (PSFilter == NULL) { sputs("Memory allocation failed."); return 1; } for (I = 0; I < PSMPFLen; I++) PSFilter[I] = 0; /* Calcola la dimensione richiesta per il calcolo del filtro */ if (Cfg.PSMultExponent >= 0) { /* Calcola la potenza di due superiore a Cfg.PSFilterLen */ for(I = 1;I <= PSMPFLen;I <<= 1); I *= 1 << Cfg.PSMultExponent; } else I = PSMPFLen; /* Calcola il filtro */ sputs("FIR Filter computation..."); if (GenericFir(PSFilter,PSMPFLen, PSFilterFreqs,PSFilterM,PSFilterP,Cfg.PSNumPoints,I,FIType) == False) { sputs("FIR Filter computation failed."); return 1; } /* Alloca gli array per la deconvoluzione omomorfa */ sputs("Allocating homomorphic deconvolution arrays."); MPSig = new DLReal[PSMPFLen]; if (MPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera gli array */ for (I = 0;I < PSMPFLen;I++) MPSig[I] = 0; /* Effettua la deconvoluzione omomorfa*/ sputs("MP target response extraction homomorphic deconvolution stage..."); if (CepstrumHD(PSFilter,MPSig,NULL,PSMPFLen, Cfg.PSMultExponent) == False) { sputs("Homomorphic deconvolution failed."); return 1; } /* Effettua la finestratura del filtro a fase minima */ HalfBlackmanWindow(MPSig,Cfg.PSFilterLen,0,WRight); /* Copia il filtro a fase minima nell'array filtro */ for (I = 0;I < Cfg.PSFilterLen;I++) PSFilter[I] = MPSig[I]; /* Dealloca l'array deconvoluzione */ delete[] MPSig; break; } /* Convoluzione filtro segnale */ sputs("Target response FIR Filter convolution..."); if (DFftConvolve(&ISRevOut[WStart2],WLen2,PSFilter, Cfg.PSFilterLen,PSOutSig) == False) { perror("Convolution failed."); return 1; } /* Deallocazione array */ delete[] ISRevOut; delete[] PSFilter; /* Determina la dimensione della finestra di uscita */ if (Cfg.PSOutWindow > 0) { /* Alloca l'array temporaneo per il filtro */ PSFilter = new DLReal[Cfg.PSOutWindow]; if (PSFilter == NULL) { sputs("Memory allocation failed."); return 1; } /* Verifica il tipo di filtro */ switch (Cfg.PSFilterType[0]) { case 'L': /* Determina la finestratura filtro */ WStart2 = (PSOutSigLen - Cfg.PSOutWindow) / 2; WLen2 = Cfg.PSOutWindow; WLen3 = PSOutSigLen; /* Salva il filtro per la convoluzione test */ for (I = 0,J = WStart2;I < WLen2;I++,J++) PSFilter[I] = PSOutSig[J]; /* Effetua la finestratura filtro */ sputs("Target response signal windowing."); BlackmanWindow(PSFilter,WLen2); break; case 'M': /* Determina la finestratura filtro */ WStart2 = (WLen2 - Cfg.PSOutWindow) / 2; WLen3 = WLen2; WLen2 = Cfg.PSOutWindow; /* Salva il filtro per la convoluzione test */ for (I = 0,J = WStart2;I < WLen2;I++,J++) PSFilter[I] = PSOutSig[J]; /* Effetua la finestratura filtro */ sputs("Target response signal windowing."); BlackmanWindow(PSFilter,WLen2); break; case 'T': /* Determina la finestratura filtro */ WStart2 = (WLen2 / 2) - Cfg.ISPELowerWindow; WLen3 = WLen2; WLen2 = Cfg.PSOutWindow; /* Salva il filtro per la convoluzione test */ for (I = 0,J = WStart2;I < WLen2;I++,J++) PSFilter[I] = PSOutSig[J]; /* Effetua la finestratura filtro */ sputs("Target response signal windowing."); HalfBlackmanWindow(PSFilter,WLen2,Cfg.ISPELowerWindow,WRight); break; } } else { /* Verifica il tipo di filtro */ switch (Cfg.PSFilterType[0]) { case 'L': /* Determina la finestratura filtro */ WStart2 = 0; WLen2 = PSOutSigLen; WLen3 = PSOutSigLen; case 'M': /* Determina la finestratura filtro */ WStart2 = 0; WLen3 = WLen2; break; case 'T': /* Determina la finestratura filtro */ WStart2 = (WLen2 / 2) - Cfg.ISPELowerWindow; WLen3 = WLen2; WLen2 = PSOutSigLen - WStart2; break; } /* Alloca l'array temporaneo per il filtro */ PSFilter = new DLReal[WLen2]; if (PSFilter == NULL) { sputs("Memory allocation failed."); return 1; } /* Salva il filtro per la convoluzione test */ for (I = 0,J = WStart2;I < WLen2;I++,J++) PSFilter[I] = PSOutSig[J]; } /* Normalizzazione segnale risultante */ if (Cfg.PSNormFactor > 0) { sputs("Target response signal normalization."); if (SigNormalize(PSFilter,WLen2,Cfg.PSNormFactor, (NormType) Cfg.PSNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Verifica se si deve salvare il segnale risposta target */ if (Cfg.PSOutFile != NULL) { /* Salva la componente MP */ sputsp("Saving Target response signal: ",Cfg.PSOutFile); if (WriteSignal(Cfg.PSOutFile,PSFilter,WLen2, (IFileType) Cfg.PSOutFileType[0]) == False) { sputs("Target response signal save failed."); return 1; } } /* Deallocazione array */ delete[] PSFilterFreqs; delete[] PSFilterM; delete[] PSFilterP; /* Reimposta la lunghezza filtro */ PSOutSigLen = WLen2; /*********************************************************************************/ /* Estrazione filtro a fase minima */ /*********************************************************************************/ /* Verifica se deve essere estratto il filtro a fase minima */ if (Cfg.MSOutFile != NULL) { /* Alloca gli array per la deconvoluzione omomorfa */ sputs("Allocating homomorphic deconvolution arrays."); PSMPFLen = Cfg.MSFilterDelay + WLen2; MPSig = new DLReal[PSMPFLen]; if (MPSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Azzera gli array */ for (I = 0;I < PSMPFLen;I++) MPSig[I] = 0; /* Effettua la deconvoluzione omomorfa*/ sputs("MP filter extraction homomorphic deconvolution stage..."); if (CepstrumHD(&PSOutSig[WStart2],&MPSig[Cfg.MSFilterDelay],NULL, WLen2,Cfg.MSMultExponent) == False) { sputs("Homomorphic deconvolution failed."); return 1; } /* Verifica se si deve finestrare il filtro */ sputs("MP filter extraction windowing."); if (Cfg.MSOutWindow > 0) { HalfBlackmanWindow(&MPSig[Cfg.MSFilterDelay],Cfg.MSOutWindow - Cfg.MSFilterDelay,0,WRight); WLen1 = Cfg.MSOutWindow; } else WLen1 = PSMPFLen; /* Normalizzazione segnale risultante */ if (Cfg.MSNormFactor > 0) { sputs("Minimum phase filter normalization."); if (SigNormalize(MPSig,WLen1,Cfg.MSNormFactor, (NormType) Cfg.MSNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Salva il il filtro a fase minima */ sputsp("Saving MP filter signal: ",Cfg.MSOutFile); if (WriteSignal(Cfg.MSOutFile,MPSig,WLen1, (IFileType) Cfg.MSOutFileType[0]) == False) { sputs("MP filter signal save failed."); return 1; } /* Dealloca l'array deconvoluzione */ delete[] MPSig; } /* Deallocazione array */ delete[] PSOutSig; /*********************************************************************************/ /* Convoluzione di test */ /*********************************************************************************/ /* Verifica se va effettuata la convoluzione finale */ if (Cfg.TCOutFile != NULL) { /* Alloca l'array per la convoluzione finale */ sputs("Allocating test convolution arrays."); TCSigLen = MCOutSigLen + PSOutSigLen - 1; TCSig = new DLReal[TCSigLen]; if (TCSig == NULL) { sputs("Memory allocation failed."); return 1; } /* Effettua la convoluzione */ sputs("Convolving input signal with target response signal..."); if (DFftConvolve(OInSig,MCOutSigLen,PSFilter,PSOutSigLen,TCSig) == False) { sputs("Convolution failed."); return 1; } /* Calcola il valore RMS del segnale dopo la filtratura */ SRMSValue = GetRMSLevel(TCSig,TCSigLen); if (SRMSValue >= 0) printf("Filtered signal RMS level %f (%f dB).\n",(double) SRMSValue, (double) (20 * log10((double) SRMSValue))); else printf("Filtered signal RMS level %f (-inf dB).\n",(double) SRMSValue); fflush(stdout); /* Normalizzazione segnale risultante */ if (Cfg.TCNormFactor > 0) { sputs("Test convolution signal normalization."); if (SigNormalize(TCSig,TCSigLen,Cfg.TCNormFactor, (NormType) Cfg.TCNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Calcola la dimensione in uscita */ if (Cfg.PSFilterType[0] == 'T') WLen3 = MCOutSigLen + 2 * Cfg.ISPELowerWindow; else WLen3 = TCSigLen; /* Salva il segnale convoluzione test */ sputsp("Saving test convolution signal: ",Cfg.TCOutFile); if (WriteSignal(Cfg.TCOutFile,TCSig,WLen3, (IFileType) Cfg.TCOutFileType[0]) == False) { sputs("Test convolution save failed."); return 1; } /* Effettua la sovrascrittura del segnale convoluzione test */ if (Cfg.TCOWFile != NULL) { sputsp("Saving test convolution overwrite: ",Cfg.TCOWFile); /* Normalizzazione segnale risultante */ if (Cfg.TCOWNormFactor > 0) { sputs("Test convolution overwrite signal normalization."); if (SigNormalize(TCSig,TCSigLen,Cfg.TCOWNormFactor, (NormType) Cfg.TCOWNormType[0]) == False) { sputs("Normalization failed."); return 1; } } /* Controlla il tipo di filtro */ if (Cfg.PSFilterType[0] == 'T') { if (((MCOutSigLen / 2 + Cfg.ISPELowerWindow) - Cfg.TCOWPrewindow) < (TCSigLen - Cfg.TCOWLength)) WLen3 = Cfg.TCOWLength; else WLen3 = TCSigLen - ((MCOutSigLen / 2 + Cfg.ISPELowerWindow) - Cfg.TCOWPrewindow); if (OverwriteSignal(Cfg.TCOWFile,&TCSig[(MCOutSigLen / 2 + Cfg.ISPELowerWindow) - Cfg.TCOWPrewindow], WLen3,Cfg.TCOWSkip,(IFileType) Cfg.TCOWFileType[0]) == False) { sputs("Test convolution overwrite failed."); return 1; } } else { if ((TCSigLen / 2 - Cfg.TCOWPrewindow) < (TCSigLen - Cfg.TCOWLength)) WLen3 = Cfg.TCOWLength; else WLen3 = TCSigLen / 2 + Cfg.TCOWPrewindow; if (OverwriteSignal(Cfg.TCOWFile,&TCSig[TCSigLen / 2 - Cfg.TCOWPrewindow], WLen3,Cfg.TCOWSkip,(IFileType) Cfg.TCOWFileType[0]) == False) { sputs("Test convolution overwrite failed."); return 1; } } } /* Dealloca gli array temporanei */ delete[] TCSig; } /* Dealloca gli array temporanei */ if (Cfg.TCOutFile != NULL || Cfg.PTType[0] != 'N') delete[] OInSig; /* Dealloca il filtro convoluzione test */ delete[] PSFilter; /* Libera la memoria della struttura di configurazione */ CfgFree(CfgParmsDef); free(DRCFile); /* Esecuzione completata */ sputs("Execution completed."); /* Segnala la durata */ printf("Total computing time: %lu s\n",(unsigned long int) (time(NULL) - CStart)); fflush(stdout); return 0; } drc-3.2.2/source/fir.cpp0000644000076400001450000002473213162156312014045 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : Fir.cpp Autore : Sbragion Denis Descrizione : Funzioni per il calcolo di filtri fir. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #include "fir.h" #include "fft.h" #include "spline.h" #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif void LowPassFir(DLReal * Filter,unsigned int Order,DLReal Freq) { unsigned int I,J,K; unsigned int HalfOrder = Order/2; DLReal C = (DLReal) (M_PI*Freq); DLReal FV; if (Order > 1) { if (Order%2 == 0) for(I = 1,J = HalfOrder - 1,K = HalfOrder; I <= HalfOrder;I++,J--,K++) { FV = (DLReal) (I-((DLReal) 0.5)); FV = (DLReal) (DLSin(FV*C)/(FV*((DLReal) M_PI))); Filter[J] = FV; Filter[K] = FV; } else { for(I = 1,J = HalfOrder - 1,K = HalfOrder + 1; I <= HalfOrder;I++,J--,K++) { FV = (DLReal) (DLSin(I*C)/(I*((DLReal) M_PI))); Filter[J] = FV; Filter[K] = FV; } Filter[HalfOrder] = Freq; } } } void HighPassFir(DLReal * Filter,unsigned int Order,DLReal Freq) { unsigned int I,HalfOrder; DLReal C = (DLReal) (M_PI*Freq); if (Order > 2) { if (Order%2 == 0) { Order--; Filter[Order] = 0; } HalfOrder = Order/2; for(I = 1; I <= HalfOrder;I++) { Filter[HalfOrder-I] = (DLReal) (-DLSin(I*C)/(I*M_PI)); Filter[HalfOrder+I] = Filter[HalfOrder-I]; } Filter[HalfOrder] = 1-Freq; } } void BandPassFir(DLReal * Filter,unsigned int Order,DLReal Low,DLReal High) { unsigned int I,HalfOrder = Order/2; DLReal D = (DLReal) (M_PI*(High-Low)/2), S = (DLReal) (M_PI*(High+Low)/2); if (Order > 1) { if (Order%2 == 0) { for(I = 1;I <= HalfOrder;I++) { Filter[HalfOrder-I] = (DLReal) ((2 / M_PI)*DLSin((I-0.5)*D)* DLCos((I-0.5)*S)/(I-0.5)); Filter[HalfOrder+I-1] = Filter[HalfOrder-I]; } } else { for(I = 1;I <= HalfOrder;I++) { Filter[HalfOrder-I] = (DLReal) ((2 / M_PI)*DLSin(I*D)* DLCos(I*S)/I); Filter[HalfOrder+I] = Filter[HalfOrder-I]; } Filter[HalfOrder] = (High-Low); } } } void BandStopFir(DLReal * Filter,unsigned int Order,DLReal Low,DLReal High) { unsigned int I,HalfOrder; DLReal D = (DLReal) (M_PI*(High-Low)/2),S = (DLReal) (M_PI*(High+Low)/2); if (Order > 2) { if (Order%2 == 0) { Order--; Filter[Order] = 0; } HalfOrder = Order/2; for(I = 1; I <= HalfOrder;I++) { Filter[HalfOrder-I] = (DLReal) (-M_2PI*DLSin(I*D)* DLCos(I*S)/I); Filter[HalfOrder+I] = Filter[HalfOrder-I]; } Filter[HalfOrder] = 1-(High-Low); } } void HilbertFir(DLReal * Filter,unsigned int Order) { unsigned int I,HalfOrder; if (Order > 2) { if (Order%2 == 0) { Order--; Filter[Order] = 0; } HalfOrder = Order/2; for(I = 1;I <= HalfOrder;I++) { Filter[HalfOrder+I] = (DLReal) (M_2PI*(I%2)/I); Filter[HalfOrder-I] = -Filter[HalfOrder+I]; } Filter[HalfOrder] = 0; } } Boolean GenericFir(DLReal * Filter,unsigned int Order,DLReal * F, DLReal * M, DLReal * P,unsigned int Np,unsigned int Is, InterpolationType It) { DLComplex * Ht; DLReal * Hf; unsigned int I,HalfFilter,HtSize,HtSize2; DLReal * LF; DLReal * LM; DLReal * LP; if ((Order < 2) || (Np < 2)) return(False); if ((F[0] != 0) || (F[Np-1] != 1)) return(False); for(I = 0;I < Np-1;I++) if (F[I] > F[I+1]) return(False); if (Is == 0) for (HtSize = 2;HtSize < Order;HtSize <<= 1); else HtSize = Is; if (HtSize < Order) return(False); HtSize2 = 2*HtSize; if ((Ht = new DLComplex[HtSize2]) == NULL) return(False); if ((Hf = new DLReal[HtSize]) == NULL) { delete[](Ht); return(False); } for(I = 0;I < HtSize;I++) Hf[I] = I / (HtSize - (DLReal) 1.0); switch (It) { case Linear: CSLCASplineValue(F,M,P,Np,Hf,HtSize,Ht,CSLLinear,CSLLinXLinY); break; case Logarithmic: /* Alloca gli array temporanei rimappatura logaritmica */ if ((LF = new DLReal[Np]) == NULL) { delete[](Ht); delete[](Hf); return(False); } if ((LM = new DLReal[Np]) == NULL) { delete[](LF); delete[](Ht); delete[](Hf); return(False); } if ((LP = new DLReal[Np]) == NULL) { delete[](LM); delete[](LF); delete[](Ht); delete[](Hf); return(False); } /* Rimappa i valori per evitare l'interpolazione a frequenza 0. Il primo elemento viene interpolato linearmente. */ LF[0] = L1SplineValue(F,F,Np,Hf[1]); LM[0] = L1SplineValue(F,M,Np,Hf[1]); LP[0] = L1SplineValue(F,P,Np,Hf[1]); for(I = 1;I < Np;I++) { LF[I] = F[I]; LM[I] = M[I]; LP[I] = P[I]; } Ht[0] = std::polar(M[0],P[0]); if (CSLCASplineValue(LF,LM,LP,Np,&Hf[1],HtSize-1,&Ht[1],CSLLinear,CSLLogXLogY) == False) { delete[](LP); delete[](LM); delete[](LF); delete[](Ht); delete[](Hf); return(False); } /* Dealloca gli array temporanei rimappatura logaritmica */ delete[](LP); delete[](LM); delete[](LF); break; case SplineLinear: if (CSLCASplineValue(F,M,P,Np,Hf,HtSize,Ht,CSLBSpline,CSLLinXLinY) == False) { delete[](Ht); delete[](Hf); return(False); } break; case SplineLogarithmic: /* Alloca gli array temporanei rimappatura logaritmica */ if ((LF = new DLReal[Np]) == NULL) { delete[](Ht); delete[](Hf); return(False); } if ((LM = new DLReal[Np]) == NULL) { delete[](LF); delete[](Ht); delete[](Hf); return(False); } if ((LP = new DLReal[Np]) == NULL) { delete[](LM); delete[](LF); delete[](Ht); delete[](Hf); return(False); } /* Rimappa i valori per evitare l'interpolazione a frequenza 0. Il primo elemento viene interpolato linearmente. */ LF[0] = L1SplineValue(F,F,Np,Hf[1]); LM[0] = L1SplineValue(F,M,Np,Hf[1]); LP[0] = L1SplineValue(F,P,Np,Hf[1]); for(I = 1;I < Np;I++) { LF[I] = F[I]; LM[I] = M[I]; LP[I] = P[I]; } Ht[0] = std::polar(M[0],P[0]); if (CSLCASplineValue(LF,LM,LP,Np,&Hf[1],HtSize-1,&Ht[1],CSLBSpline,CSLLogXLogY) == False) { delete[](LP); delete[](LM); delete[](LF); delete[](Ht); delete[](Hf); return(False); } /* Dealloca gli array temporanei rimappatura logaritmica */ delete[](LP); delete[](LM); delete[](LF); break; case PCHIPLinear: if (CSLCASplineValue(F,M,P,Np,Hf,HtSize,Ht,CSLHSSpline,CSLLinXLinY) == False) { delete[](Ht); delete[](Hf); return(False); } break; case PCHIPLogarithmic: /* Alloca gli array temporanei rimappatura logaritmica */ if ((LF = new DLReal[Np]) == NULL) { delete[](Ht); delete[](Hf); return(False); } if ((LM = new DLReal[Np]) == NULL) { delete[](LF); delete[](Ht); delete(Hf); return(False); } if ((LP = new DLReal[Np]) == NULL) { delete[](LM); delete[](LF); delete[](Ht); delete[](Hf); return(False); } /* Rimappa i valori per evitare l'interpolazione a frequenza 0. Il primo elemento viene interpolato linearmente. */ LF[0] = L1SplineValue(F,F,Np,Hf[1]); LM[0] = L1SplineValue(F,M,Np,Hf[1]); LP[0] = L1SplineValue(F,P,Np,Hf[1]); for(I = 1;I < Np;I++) { LF[I] = F[I]; LM[I] = M[I]; LP[I] = P[I]; } Ht[0] = std::polar(M[0],P[0]); if (CSLCASplineValue(LF,LM,LP,Np,&Hf[1],HtSize-1,&Ht[1],CSLHSSpline,CSLLogXLogY) == False) { delete[](LP); delete[](LM); delete[](LF); delete[](Ht); delete[](Hf); return(False); } /* Dealloca gli array temporanei rimappatura logaritmica */ delete[](LP); delete[](LM); delete[](LF); break; } if (Order%2 == 0) { for(I = 1;I < HtSize;I++) Ht[HtSize2-I] = -std::conj(Ht[I]); Ht[HtSize] = std::polar(M[Np-1],P[Np-1]); for (I = 0;I < HtSize2;I++) Ht[I] *= UnitRoot(I,2*HtSize2); } else { for(I = 1;I < HtSize;I++) Ht[2*HtSize-I] = std::conj(Ht[I]); Ht[HtSize] = std::polar(M[Np-1],P[Np-1]); } if (IFft(Ht,HtSize2) == False) { delete[](Ht); return(False); } HalfFilter = Order/2; for(I = 0;I < HalfFilter;I++) Filter[I] = std::real(Ht[HtSize2-HalfFilter+I]); for(I = HalfFilter;I < Order;I++) Filter[I] = std::real(Ht[I-HalfFilter]); delete[](Ht); delete[](Hf); return(True); } /***************************************************************************/ drc-3.2.2/source/lsconv.c0000644000076400001450000002613313165104130014220 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2004 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@neomerica.it ****************************************************************************/ /* Log sweep and inverse filter convolution program */ /* Includes */ #include #include #include #include "fftsg_h.h" /* Output stringhe con sync output e parametro */ int sputsp(const char * s, const char * p) { int Res; if (p == NULL) Res = puts(s); else Res = printf("%s%s\n",s,p); fflush(stdout); return(Res); } /* Output stringhe con sync output */ int sputs(const char * s) { return(sputsp(s, NULL)); } /* Determina la lunghezza di un file */ size_t FSize(char * FName) { long FS; FILE * F; if ((F = fopen(FName,"rb")) == NULL) { perror("Unable to open file"); return 0; } fseek(F,0,SEEK_END); FS = ftell(F); fclose(F); return (size_t) FS; } /* Calola il valore RMS del segnale Sig */ DLReal GetRMSLevel(const DLReal * Sig,const int SigLen) { DLReal RMS; int I; RMS = 0; for (I = 0; I < SigLen; I++) RMS += Sig[I] * Sig[I]; return (DLReal) sqrt(RMS); } /* Halfcomplex array convolution */ void hcconvolve(DLReal * A,const DLReal * B,const int N) { int R; int I; DLReal T1; DLReal T2; A[0] *= B[0]; A[1] *= B[1]; for (R = 2,I = 3;R < N;R += 2,I += 2) { T1 = A[R] * B[R]; T2 = A[I] * B[I]; A[I] = ((A[R] + A[I]) * (B[R] + B[I])) - (T1 + T2); A[R] = T1 - T2; } } /* Main procedure */ int main(int argc, char * argv[]) { /* Input parameters */ char * SweepFile; char * InverseFile; char * OutFile; char * RefSweepFile; DLReal MinGain = 0; DLReal DLStart; /* Convolution parameters */ int SS; int IS; int RS; int CS; int CL; int I; int J; DLReal * Sweep; DLReal * Inverse; float RF; /* Dip limiting */ DLReal RMSLevel; DLReal RMSMin; DLReal DLSLevel; DLReal DLLevel; DLReal DLGFactor; DLReal DLAbs; DLReal DLTheta; /* Peak position */ int MP; DLReal AMax; /* Input/output file */ FILE * IOF; /* Initial message */ sputs("\nLSConv 1.1.0: log sweep and inverse filter convolution."); sputs("Copyright (C) 2002-2011 Denis Sbragion"); #ifdef UseDouble sputs("\nCompiled with double precision arithmetic."); #else sputs("\nCompiled with single precision arithmetic."); #endif sputs("\nThis program may be freely redistributed under the terms of"); sputs("the GNU GPL and is provided to you as is, without any warranty"); sputs("of any kind. Please read the file \"COPYING\" for details."); /* Check program arguments */ if (argc < 4 || (argc > 4 && argc < 6)) { sputs("\nUsage: LSConv sweepfile inversefile outfile [refsweep mingain [dlstart]]"); sputs("\nParameters:\n"); sputs(" sweepfile: sweep file name"); sputs(" inversefile: inverse sweep file name"); sputs(" outfile: output impulse response file"); sputs(" refsweep: reference channel sweep file name"); sputs(" mingain: min gain for reference channel inversion"); sputs(" dlstart: dip limiting start for reference channel inversion"); sputs("\nExample: lsconv sweep.pcm inverse.pcm impulse.pcm refchannel.pcm 0.1 0.8\n"); return 0; } /* Get the input parameters from the command line */ sputs("\nCommand line parsing."); SweepFile = argv[1]; InverseFile = argv[2]; OutFile = argv[3]; if (argc > 4) { RefSweepFile = argv[4]; MinGain = (DLReal) atof(argv[5]); } else RefSweepFile = NULL; if (argc >= 7) DLStart = (DLReal) atof(argv[6]); else DLStart = (DLReal) 2.0; /* Computes the convolution length */ sputs("Convolution length computation."); SS = FSize(SweepFile) / sizeof(float); IS = FSize(InverseFile) / sizeof(float); if (RefSweepFile != NULL) RS = FSize(RefSweepFile) / sizeof(float); else RS = 1; CL = SS + IS + RS - 2; for(CS = 1;CS < CL;CS <<= 1); /* Convolution arrays allocation */ sputs("Convolution arrays allocation."); if ((Sweep = (DLReal *) malloc(sizeof(DLReal) * CS)) == NULL) { sputs("Memory allocation failure."); return 1; } if ((Inverse = (DLReal *) malloc(sizeof(DLReal) * CS)) == NULL) { sputs("Memory allocation failure."); free(Sweep); return 1; } /* Read the inverse file */ sputsp("Reading inverse file: ",InverseFile); if ((IOF = fopen(InverseFile,"rb")) == NULL) { perror("Unable to open inverse file"); return 1; } for(I = 0;I < IS;I++) { if (fread(&RF,sizeof(float),1,IOF) < sizeof(float)) { perror("Error while reading the inverse file"); return 1; } Inverse[I] = (DLReal) RF; } for (I = IS;I < CS;I++) Inverse[I] = (DLReal) 0.0; fclose(IOF); sputs("Inverse filter FFT..."); rdft(CS,OouraRForward,Inverse); /* Check the reference file */ if (RefSweepFile != NULL) { /* Read the reference file */ sputsp("Reading reference file: ",RefSweepFile); if ((IOF = fopen(RefSweepFile,"rb")) == NULL) { perror("Unable to open reference file"); return 1; } for (I = 0;I < CS;I++) Sweep[I] = (DLReal) 0.0; for(I = CS - IS,J = 0;J < RS;I++,J++) { if (fread(&RF,sizeof(float),1,IOF) < sizeof(float)) { perror("Error while reading the reference file"); return 1; } Sweep[I % CS] = (DLReal) RF; } fclose(IOF); /* Convolving sweep and inverse */ sputs("Reference inversion and convolution..."); rdft(CS,OouraRForward,Sweep); hcconvolve(Sweep,Inverse,CS); /* Computes the RMS Level */ RMSLevel = Sweep[0] * Sweep[0]; for (I = 2,J = 3;I < CS;I += 2,J += 2) RMSLevel += Sweep[I] * Sweep[I] + Sweep[J] * Sweep[J]; RMSLevel = (DLReal) sqrt(2.0 * RMSLevel / CS); RMSMin = MinGain * RMSLevel; /* Check the gain truncation type */ if (DLStart >= (DLReal) 1.0) { /* Check starting components */ if (Sweep[0] < RMSMin) Sweep[0] = ((DLReal) 1.0) / RMSMin; else Sweep[0] = ((DLReal) 1.0) / Sweep[0]; if (Sweep[1] < RMSMin) Sweep[1] = ((DLReal) 1.0) / RMSMin; else Sweep[1] = ((DLReal) 1.0) / Sweep[1]; /* Gain truncation scan */ for (I = 2,J = 3;I < CS;I += 2,J += 2) { /* Gain computation */ DLAbs = (DLReal) hypot(Sweep[I],Sweep[J]); /* Gain check and limitation */ if (DLAbs < RMSMin) { /* Gain limited inversion */ DLTheta = (DLReal) atan2(Sweep[J],Sweep[I]); DLAbs = ((DLReal) 1.0) / RMSMin; Sweep[I] = DLAbs * (DLReal) cos(-DLTheta); Sweep[J] = DLAbs * (DLReal) sin(-DLTheta); } else { /* Inversion and renormalization */ DLAbs = ((DLReal) 1.0) / (DLAbs * DLAbs); Sweep[I] *= DLAbs; Sweep[J] *= -DLAbs; } } } else { /* Determina i fattori per la limitazione guadagno */ DLSLevel = RMSMin / DLStart; DLGFactor = DLSLevel - RMSMin; /* Check starting components */ if (Sweep[0] < DLSLevel) { /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - Sweep[0]) / DLGFactor; DLLevel = DLLevel / (((DLReal) 1.0) + DLLevel); Sweep[0] = ((DLReal) 1.0) / (DLSLevel - DLGFactor * DLLevel); } else Sweep[0] = ((DLReal) 1.0) / Sweep[0]; if (Sweep[1] < DLSLevel) { /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - Sweep[1]) / DLGFactor; DLLevel = DLLevel / (((DLReal) 1.0) + DLLevel); Sweep[1] = ((DLReal) 1.0) / (DLSLevel - DLGFactor * DLLevel); } else Sweep[1] = ((DLReal) 1.0) / Sweep[1]; /* Scansione per limitazione guadagno */ for (I = 2,J = 3;I < CS;I += 2,J += 2) { DLAbs = (DLReal) hypot(Sweep[I],Sweep[J]); if (DLAbs <= (DLReal) 0.0) { Sweep[I] = ((DLReal) 1.0) / RMSMin; Sweep[J] = 0; } else if (DLAbs < DLSLevel) { /* Riassegna il guadagno del filtro */ DLLevel = (DLSLevel - DLAbs) / DLGFactor; DLLevel = DLLevel / (((DLReal) 1.0) + DLLevel); DLAbs = ((DLReal) 1.0) / (DLSLevel - DLGFactor * DLLevel); /* Gain limited inversion */ DLTheta = (DLReal) atan2(Sweep[J],Sweep[I]); Sweep[I] = DLAbs * (DLReal) cos(-DLTheta); Sweep[J] = DLAbs * (DLReal) sin(-DLTheta); } else { /* Inversion and renormalization */ DLAbs = ((DLReal) 1.0) / (DLAbs * DLAbs); Sweep[I] *= DLAbs; Sweep[J] *= -DLAbs; } } } /* Inverse convolution */ hcconvolve(Inverse,Sweep,CS); } /* Read the sweep file */ sputsp("Reading sweep file: ",SweepFile); if ((IOF = fopen(SweepFile,"rb")) == NULL) { perror("Unable to open sweep file"); return 1; } for(I = 0;I < SS;I++) { if (fread(&RF,sizeof(float),1,IOF) < sizeof(float)) { perror("Error while reading the sweep file"); return 1; } Sweep[I] = (DLReal) RF; } fclose(IOF); for (I = SS;I < CS;I++) Sweep[I] = (DLReal) 0.0; /* Convolving sweep and inverse */ sputs("Sweep and inverse convolution..."); rdft(CS,OouraRForward,Sweep); hcconvolve(Sweep,Inverse,CS); /* Impulse response recover */ rdft(CS,OouraRBackward,Sweep); for (I = 0;I < CS;I++) Sweep[I] *= (DLReal) (2.0 / CS); /* Peak search */ sputs("Finding impulse response peak value..."); MP = 0; AMax = (DLReal) 0.0; for (I = 0;I < CS;I++) if ((DLReal) fabs(Sweep[I]) > AMax) { MP = I; AMax = (DLReal) fabs(Sweep[I]); } printf("Peak position: %d\n",MP); if (AMax > (DLReal) 0.0) printf("Peak value: %f (%f dB)\n",(double) AMax, (double) (20 * log10((double) AMax))); else printf("Peak value: %f (-inf dB)\n",(double) AMax); fflush(stdout); /* Writes output file */ sputsp("Writing output file: ",OutFile); if ((IOF = fopen(OutFile,"wb")) == NULL) { perror("Unable to open output file"); return 1; } for(I = 0;I < CL;I++) { RF = (float) Sweep[I]; fwrite(&RF,sizeof(float),1,IOF); } fclose(IOF); /* Memory deallocation */ free(Sweep); free(Inverse); /* Execution completed */ sputs("Completed."); return 0; } drc-3.2.2/source/copying0000644000076400001450000004307610250053164014152 0ustar denisitadm GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. drc-3.2.2/source/drc.cbp0000644000076400001450000002613113165106030014005 0ustar denisitadm drc-3.2.2/source/toeplitz.h0000644000076400001450000000264513162156312014603 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Risolve il sistema di equazioni: AX = B dove A una matrice Toeplitz simmetrica di dimensione N. In A va posta solo la prima riga della matrice. Per la soluzione viene usato il classico metodo di Levinson. Ritorna 0 in caso di successo, 1 altrimenti. */ #ifndef Toeplitz_h #define Toeplitz_h #include "dsplib.h" int ToeplitzSolve(const DLReal * A, const DLReal * B, DLReal * X, int N); #endif drc-3.2.2/source/spline.cpp0000644000076400001450000007071413165105367014567 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2017 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@neomerica.it ****************************************************************************/ /* Spline routines */ /* Inclusioni */ #include "spline.h" #include #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Valore della spline lineare nel punto X */ DLReal L1SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal X) { int IP; int IL; int IR; /* Recupera l'intervallo interessato */ IL = 0; IR = N - 1; while (IR - IL > 1) { IP = (IR + IL) >> 1; if (XN[IP] > X) IR = IP; else IL = IP; } /* Ritorna il valore calcolato */ return YN[IL] + ((X - XN[IL]) / (XN[IR] - XN[IL])) * (YN[IR] - YN[IL]); } /* Valore della spline lineare nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void AL1SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y) { /* Indici ricerca array spline */ int ISL; int ISU; int ISP; /* Inici ricerca array funzione */ int IFL; int IFU; int IFP; /* X Corrente */ int IXP; DLReal CX; /* Estremi correnti array spline */ DLReal XNL; DLReal XNU; DLReal YNL; DLReal YNU; /* Variabili intermedie calcolo spline */ DLReal DX; DLReal DY; /* Ciclo sui punti disponibili */ IXP = 0; ISL = 0; while (IXP < XS) { /* Estrae il punto corrente */ CX = X[IXP]; /* Recupera il primo intervallo spline interessato */ ISU = N - 1; while (ISU - ISL > 1) { ISP = (ISU + ISL) >> 1; if (XN[ISP] > CX) ISU = ISP; else ISL = ISP; } /* Estrae i valori di riferimento per l'intervallo spline corrente */ XNL = XN[ISL]; XNU = XN[ISU]; YNL = YN[ISL]; YNU = YN[ISU]; DX = XNU - XNL; DY = YNU - YNL; /* Estrae il punto massimo per l'intervallo funzione corrente */ IFU = XS - 1; IFL = IXP; while (IFU - IFL > 1) { IFP = (IFU + IFL) >> 1; if (X[IFP] > XNU) IFU = IFP; else IFL = IFP; } /* Aggiunge l'ultimo punto a fine spline */ if (ISU == N - 1) IFU++; /* Ciclo creazione valori spline */ while (IXP < IFU) { /* Estrae il punto corrente */ CX = X[IXP]; /* Imposta il valore nel punto */ Y[IXP] = YNL + DY * ((CX - XNL) / DX); /* Passa al punto successivo */ IXP++; } } } /* Prepara la base per la spline cubica interpolante, ponendola in SPD2YN */ static void IFSplinePrepare(const DLReal * XN, const DLReal * YN, const int N, const DLReal SPD1Y1, const DLReal SPD1YN, const CSplineType SPType, DLReal * SPD2YN, DLReal * UN) { int IM1; int I; int IP1; DLReal P; DLReal Q = 0; DLReal S; DLReal U = 0; /* Verifica il tipo di condizioni al contorno */ switch (SPType) { case SplineBDef: SPD2YN[0] = (DLReal) -0.5; UN[0] = (((DLReal) 3.0) / (XN[1] - XN[0])) * ((YN[1] - YN[0]) / (XN[1] - XN[0]) - SPD1Y1); break; case SplineBNat: SPD2YN[0] = (DLReal) 0.0; UN[0] = (DLReal) 0.0; break; } /* Decomposizione sistema tridiagonale */ for (IM1 = 0,I = 1,IP1 = 2;I < N - 1;IM1++,I++,IP1++) { S = (XN[I] - XN[IM1]) / (XN[IP1] - XN[IM1]); P = S * SPD2YN[IM1] + (DLReal) 2.0; SPD2YN[I] = (S - (DLReal) 1.0) / P; UN[I] = (YN[IP1] - YN[I]) / (XN[IP1] - XN[I]) - (YN[I] - YN[IM1]) / (XN[I] - XN[IM1]); UN[I] = (((DLReal) 6.0) * UN[I] / (XN[IP1] - XN[IM1]) - S * UN[IM1]) / P; } /* Verifica il tipo di condizioni al contorno */ switch (SPType) { case SplineBDef: Q = (DLReal) 0.5; U = (((DLReal) 3.0) / (XN[N - 1] - XN[N - 2])) * (SPD1YN - (YN[N - 1] - YN[N - 2]) / (XN[N - 1] - XN[N - 2])); break; case SplineBNat: Q = (DLReal) 0.0; U = (DLReal) 0.0; break; } /* Sostituzione all'indietro per recupero derivate */ SPD2YN[N - 1] = (U - Q * UN[N - 2]) / (Q * SPD2YN[N - 2] + ((DLReal) 1.0)); for (I = N - 2,IP1 = N - 1;I >= 0;I--,IP1--) SPD2YN[I] = SPD2YN[I] * SPD2YN[IP1] + UN[I]; } /* Prepara la base per la spline cubica interpolante, ponendola in SPD2YN */ Boolean SplinePrepare(const DLReal * XN, const DLReal * YN, const int N, const DLReal SPD1Y1, const DLReal SPD1YN, const CSplineType SPType, DLReal * SPD2YN) { DLReal * UN; /* Alloca l'array intermedio calcolo spline */ if ((UN = (DLReal *) malloc((N - 1) * sizeof(DLReal))) == NULL) return False; /* Effettua la preparazione della spline */ IFSplinePrepare(XN, YN, N, SPD1Y1, SPD1YN, SPType, SPD2YN, UN); /* Dealloca il vettore temporaneo */ free(UN); /* Operazione completata */ return True; } /* Valore della spline cubica interpolante nel punto X */ DLReal SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * SPD2YN, const DLReal X) { int II; int IS; int IP; DLReal DX; DLReal W; DLReal Q; /* Recupera l'intervallo interessato */ II = 0; IS = N - 1; while (IS - II > 1) { IP = (IS + II) >> 1; if (XN[IP] > X) IS = IP; else II = IP; } /* Calcola il valore nel punto */ DX = XN[IS] - XN[II]; W = (XN[IS] - X) / DX; Q = (X - XN[II]) / DX; return W * YN[II] + Q * YN[IS] + ((W * W * W - W) * SPD2YN[II] + (Q * Q * Q - Q) * SPD2YN[IS]) * (DX * DX) / (DLReal) 6.0; } /* Valore della spline cubica interpolante nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void ASplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * SPD2YN, const DLReal * X, const int XS, DLReal * Y) { /* Indici ricerca array spline */ int ISL; int ISU; int ISP; /* Inici ricerca array funzione */ int IFL; int IFU; int IFP; /* X Corrente */ int IXP; DLReal CX; /* Estremi correnti array spline */ DLReal XNL; DLReal XNU; DLReal YNL; DLReal YNU; DLReal SPD2YNL; DLReal SPD2YNU; /* Variabili intermedie calcolo spline */ DLReal DX; DLReal W; DLReal Q; DLReal DX2; /* Ciclo sui punti disponibili */ IXP = 0; ISL = 0; while (IXP < XS) { /* Estrae il punto corrente */ CX = X[IXP]; /* Recupera il primo intervallo spline interessato */ ISU = N - 1; while (ISU - ISL > 1) { ISP = (ISU + ISL) >> 1; if (XN[ISP] > CX) ISU = ISP; else ISL = ISP; } /* Estrae i valori di riferimento per l'intervallo spline corrente */ XNL = XN[ISL]; XNU = XN[ISU]; DX = XNU - XNL; DX2 = DX * DX; YNL = YN[ISL]; YNU = YN[ISU]; SPD2YNL = SPD2YN[ISL]; SPD2YNU = SPD2YN[ISU]; /* Estrae il punto massimo per l'intervallo funzione corrente */ IFU = XS - 1; IFL = IXP; while (IFU - IFL > 1) { IFP = (IFU + IFL) >> 1; if (X[IFP] > XNU) IFU = IFP; else IFL = IFP; } /* Aggiunge l'ultimo punto a fine spline */ if (ISU == N - 1) IFU++; /* Ciclo creazione valori spline */ while (IXP < IFU) { /* Estrae il punto corrente */ CX = X[IXP]; /* Imposta i valori intermedi calcolo spline */ W = (XNU - CX) / DX; Q = (CX - XNL) / DX; /* Calcola il valore nel punto */ Y[IXP] = W * YNL + Q * YNU + ((W * W * W - W) * SPD2YNL + (Q * Q * Q - Q) * SPD2YNU) * DX2 / (DLReal) 6.0; /* Passa al punto successivo */ IXP++; } } } /* Valore della B spline cubica uniforme nel punto X */ DLReal B3SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal X) { DLReal BV; DLReal RX; DLReal Y; int IP; int IL; int IR; /* Recupera l'intervallo interessato */ IL = 0; IR = N - 1; while (IR - IL > 1) { IP = (IR + IL) >> 1; if (XN[IP] > X) IR = IP; else IL = IP; } /* Rimappa X secondo l'intervallo corrente */ RX = (X - XN[IL]) / (XN[IR] - XN[IL]); /* Inizializza il valore */ Y = (DLReal) 0.0; /* Fattore di blending per IL - 1 */ /* (((-t+3)*t-3)*t+1)/6 */ BV = (((-RX + (DLReal) 3.0) * RX - (DLReal) 3.0) * RX + (DLReal) 1.0) / (DLReal) 6.0; if (IL > 0) Y += YN[IL - 1] * BV; else Y += (((DLReal) 2.0) * YN[0] - YN[1]) * BV; /* Fattore di blending per IL */ /* (((3*t-6)*t)*t+4)/6 */ BV = (((((DLReal) 3.0) * RX - (DLReal) 6.0) * RX) * RX + (DLReal) 4.0) / (DLReal) 6.0; Y += YN[IL] * BV; /* Fattore di blending per IR */ /* (((-3*t+3)*t+3)*t+1)/6 */ BV = (((((DLReal) -3.0) * RX + (DLReal) 3.0) * RX + (DLReal) 3.0) * RX + (DLReal) 1.0) / (DLReal) 6.0; Y += YN[IR] * BV; /* Fattore di blending per IR + 1 */ /* (t*t*t)/6 */ BV = (RX * RX * RX) / (DLReal) 6.0; if (IR + 1 < N) Y += YN[IR + 1] * BV; else Y += (((DLReal) 2.0) * YN[N - 1] - YN[N - 2]) * BV; /* Ritorna il valore calcolato */ return Y; } /* Valore della B spline cubica uniforme nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void AB3SplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y) { /* Indici ricerca array spline */ int ISL; int ISU; int ISP; /* Inici ricerca array funzione */ int IFL; int IFU; int IFP; /* X Corrente */ int IXP; DLReal CX; /* X Corrente rimappato */ DLReal RX; /* Estremi correnti array spline */ DLReal XNL; DLReal XNU; DLReal YNL; DLReal YNU; DLReal YNLL; DLReal YNUU; /* Variabili intermedie calcolo spline */ DLReal DX; /* Ciclo sui punti disponibili */ IXP = 0; ISL = 0; while (IXP < XS) { /* Estrae il punto corrente */ CX = X[IXP]; /* Recupera il primo intervallo spline interessato */ ISU = N - 1; while (ISU - ISL > 1) { ISP = (ISU + ISL) >> 1; if (XN[ISP] > CX) ISU = ISP; else ISL = ISP; } /* Estrae i valori di riferimento per l'intervallo spline corrente */ XNL = XN[ISL]; XNU = XN[ISU]; YNL = YN[ISL]; YNU = YN[ISU]; if (ISL > 0) YNLL = YN[ISL - 1]; else YNLL = (((DLReal) 2.0) * YN[0] - YN[1]); if (ISU + 1 < N) YNUU = YN[ISU + 1]; else YNUU = (((DLReal) 2.0) * YN[N - 1] - YN[N - 2]); DX = XNU - XNL; /* Estrae il punto massimo per l'intervallo funzione corrente */ IFU = XS - 1; IFL = IXP; while (IFU - IFL > 1) { IFP = (IFU + IFL) >> 1; if (X[IFP] > XNU) IFU = IFP; else IFL = IFP; } /* Aggiunge l'ultimo punto a fine spline */ if (ISU == N - 1) IFU++; /* Ciclo creazione valori spline */ while (IXP < IFU) { /* Rimappa X secondo l'intervallo corrente */ RX = (X[IXP] - XNL) / DX; /* Imposta il valore nel punto */ Y[IXP] = ((YNLL * ((((-RX + (DLReal) 3.0) * RX - (DLReal) 3.0) * RX + (DLReal) 1.0))) + (YNL * ((((((DLReal) 3.0) * RX - (DLReal) 6.0) * RX) * RX + (DLReal) 4.0))) + (YNU * ((((((DLReal) -3.0) * RX + (DLReal) 3.0) * RX + (DLReal) 3.0) * RX + (DLReal) 1.0))) + (YNUU * ((RX * RX * RX)))) / ((DLReal) 6.0); /* Passa al punto successivo */ IXP++; } } } /* Valore della B spline cubica di tipo Catmull Rom nel punto X */ DLReal B3CRSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal X) { DLReal BV; DLReal RX; DLReal Y; int IP; int IL; int IR; /* Recupera l'intervallo interessato */ IL = 0; IR = N - 1; while (IR - IL > 1) { IP = (IR + IL) >> 1; if (XN[IP] > X) IR = IP; else IL = IP; } /* Rimappa X secondo l'intervallo corrente */ RX = (X - XN[IL]) / (XN[IR] - XN[IL]); /* Inizializza il valore */ Y = (DLReal) 0.0; /* Fattore di blending per IL - 1 */ /* ((-t+2)*t-1)*t/2 */ BV = (((-RX + (DLReal) 2.0) * RX - (DLReal) 1.0) * RX) / (DLReal) 2.0; if (IL > 0) Y += YN[IL - 1] * BV; else Y += (((DLReal) 2.0) * YN[0] - YN[1]) * BV; /* Fattore di blending per IL */ /* (((3*t-5)*t)*t+2)/2 */ BV = (((((DLReal) 3.0) * RX - (DLReal) 5.0) * RX) * RX + (DLReal) 2.0) / (DLReal) 2.0; Y += YN[IL] * BV; /* Fattore di blending per IR */ /* ((-3*t+4)*t+1)*t/2 */ BV = (((((DLReal) -3.0) * RX + (DLReal) 4.0) * RX + (DLReal) 1.0) * RX) / (DLReal) 2.0; Y += YN[IR] * BV; /* Fattore di blending per IR + 1 */ /* ((t-1)*t*t)/2 */ BV = ((RX - (DLReal) 1.0) * RX * RX) / (DLReal) 2.0; if (IR + 1 < N) Y += YN[IR + 1] * BV; else Y += (((DLReal) 2.0) * YN[N - 1] - YN[N - 2]) * BV; /* Ritorna il valore calcolato */ return Y; } /* Valore della B spline cubica di tipo Catmull Rom nei punti X */ /* X deve essere un array crescente strettamente monotonico */ void AB3CRSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y) { /* Indici ricerca array spline */ int ISL; int ISU; int ISP; /* Inici ricerca array funzione */ int IFL; int IFU; int IFP; /* X Corrente */ int IXP; DLReal CX; /* X Corrente rimappato */ DLReal RX; /* Estremi correnti array spline */ DLReal XNL; DLReal XNU; DLReal YNL; DLReal YNU; DLReal YNLL; DLReal YNUU; /* Variabili intermedie calcolo spline */ DLReal DX; /* Ciclo sui punti disponibili */ IXP = 0; ISL = 0; /* Verifica se rischiesto un output monotonico */ while (IXP < XS) { /* Estrae il punto corrente */ CX = X[IXP]; /* Recupera il primo intervallo spline interessato */ ISU = N - 1; while (ISU - ISL > 1) { ISP = (ISU + ISL) >> 1; if (XN[ISP] > CX) ISU = ISP; else ISL = ISP; } /* Estrae i valori di riferimento per l'intervallo spline corrente */ XNL = XN[ISL]; XNU = XN[ISU]; YNL = YN[ISL]; YNU = YN[ISU]; if (ISL > 0) YNLL = YN[ISL - 1]; else YNLL = (((DLReal) 2.0) * YN[0] - YN[1]); if (ISU + 1 < N) YNUU = YN[ISU + 1]; else YNUU = (((DLReal) 2.0) * YN[N - 1] - YN[N - 2]); DX = XNU - XNL; /* Estrae il punto massimo per l'intervallo funzione corrente */ IFU = XS - 1; IFL = IXP; while (IFU - IFL > 1) { IFP = (IFU + IFL) >> 1; if (X[IFP] > XNU) IFU = IFP; else IFL = IFP; } /* Aggiunge l'ultimo punto a fine spline */ if (ISU == N - 1) IFU++; /* Ciclo creazione valori spline */ while (IXP < IFU) { /* Rimappa X secondo l'intervallo corrente */ RX = (X[IXP] - XNL) / DX; /* Imposta il valore nel punto */ Y[IXP] = ((YNLL * ((((-RX + (DLReal) 2.0) * RX - (DLReal) 1.0) * RX))) + (YNL * ((((((DLReal) 3.0) * RX - (DLReal) 5.0) * RX) * RX + (DLReal) 2.0))) + (YNU * ((((((DLReal) -3.0) * RX + (DLReal) 4.0) * RX + (DLReal) 1.0) * RX))) + (YNUU * (((RX - (DLReal) 1.0) * RX * RX)))) / ((DLReal) 2.0); /* Passa al punto successivo */ IXP++; } } } /* Interpolazione su scala lineare tramite B spline cubica uniforme con riparametrizzazione arc length tramite B spline cubica Catmull-Rom interpolante */ Boolean AB3CRMSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y) { /* Array gestione spline rimappatura */ DLReal * SX; DLReal * IX; /* Indice generico */ int I; /* Indice recupero monotonicit */ int XP; /* Alloca l'array interpolazione parametro */ if ((SX = new DLReal[XS]) == NULL) return(False); /* Interpolazione parametro */ AB3SplineValue(XN,XN,N,X,XS,SX); /* Estrae i soli valori monotonici */ XP = 0; Y[0] = X[0]; for (I = 1;I < XS;I++) if (SX[I] > SX[XP]) { XP++; SX[XP] = SX[I]; Y[XP] = X[I]; } XP++; /* Alloca l'array rimappatura parametro */ if ((IX = new DLReal[XS]) == NULL) { delete[] SX; return(False); } /* Rimappatura parametro */ AB3CRSplineValue(SX,Y,XP,X,XS,IX); /* Dealloca l'array interpolazione parametro */ delete[] SX; /* Interpolazione spline */ AB3SplineValue(XN,YN,N,IX,XS,Y); /* Dealloca l'array rimappatura parametro */ delete[] IX; /* Operazione completata */ return True; } /* Funzione di supporto a APCHIPSplineValue. -1. if X1 and X2 are of opposite sign. 0. if either argument is zero. +1. if X1 and X2 are of the same sign. */ static int CHST(const DLReal X1, const DLReal X2) { if ((X1 > (DLReal) 0.0 && X2 > (DLReal) 0.0) || (X1 < (DLReal) 0.0 && X2 < (DLReal) 0.0)) return 1; if ((X1 > (DLReal) 0.0 && X2 < (DLReal) 0.0) || (X1 < (DLReal) 0.0 && X2 > (DLReal) 0.0)) return -1; return 0; } /* Interpolazione su scala lineare tramite Hermite spline cubica monotonica */ void APCHIPSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y) { /* Indici ricerca array spline */ int ISL; int ISU; int ISP; /* Inici ricerca array funzione */ int IFL; int IFU; int IFP; /* X Corrente */ int IXP; DLReal CX; /* X Corrente rimappato */ DLReal RX; /* Estremi correnti array spline */ DLReal XNL; DLReal XNU; DLReal YNL; DLReal YNU; /* Variabili calcolo derivate spline */ DLReal ML; DLReal MU; DLReal HP; DLReal HK; DLReal HN; DLReal DP; DLReal DK; DLReal DN; DLReal DMIN; DLReal DMAX; /* Variabili intermedie calcolo spline */ DLReal C1; DLReal C2; DLReal C3; DLReal C4; /* Ciclo sui punti disponibili */ IXP = 0; ISL = 0; while (IXP < XS) { /* Estrae il punto corrente */ CX = X[IXP]; /* Recupera il primo intervallo spline interessato */ ISU = N - 1; while (ISU - ISL > 1) { ISP = (ISU + ISL) >> 1; if (XN[ISP] > CX) ISU = ISP; else ISL = ISP; } /* Estrae i valori di riferimento per l'intervallo spline corrente */ XNL = XN[ISL]; XNU = XN[ISU]; YNL = YN[ISL]; YNU = YN[ISU]; HK = XNU - XNL; DK = (YNU - YNL) / HK; /* Calcola le derivate per gli estremi del segmento corrente */ if (N == 2) { /* Interpolazione lineare */ ML = DK; MU = DK; } else { /* Derivata inferiore */ if (ISL == 0) { /* Punto estremo */ HN = (XN[ISU + 1] - XNU); DN = (YN[ISU + 1] - YNU) / HN; ML = HK + HN; ML = ((DK * (ML + HK)) - (DN * HK)) / ML; if (CHST(ML,DK) <= 0) ML = (DLReal) 0.0; else if (CHST(DK,DN) < 0) { DMAX = 3 * DK; if (std::abs(ML) > std::abs(DMAX)) ML = DMAX; } } else { /* Punto intermedio */ HP = (XNL - XN[ISL - 1]); DP = (YNL - YN[ISL - 1]) / HP; if (CHST(DP,DK) > 0) { C1 = std::abs(DP); C2 = std::abs(DK); if (C1 < C2) { DMIN = C1; DMAX = C2; } else { DMIN = C2; DMAX = C1; } C4 = HP + HK; C3 = C4 + C4 + C4; C1 = (C4 + HP)/C3; C2 = (C4 + HK)/C3; C3 = DP / DMAX; C4 = DK / DMAX; ML = DMIN / (C1 * C3 + C2 * C4); } else ML = (DLReal) 0.0; } /* Derivata superiore */ if (ISU == N - 1) { /* Punto estremo */ HP = (XNL - XN[ISL - 1]); DP = (YNL - YN[ISL - 1]) / HP; MU = HP + HK; MU = ((DK * (MU + HK)) - (DP * HK)) / MU; if (CHST(MU,DK) <= 0) MU = (DLReal) 0.0; else if (CHST(DP,DK) < 0) { DMAX = 3 * DK; if (std::abs(MU) > std::abs(DMAX)) MU = DMAX; } } else { /* Punto intermedio */ HN = (XN[ISU + 1] - XNU); DN = (YN[ISU + 1] - YNU) / HN; if (CHST(DK,DN) > 0) { C1 = std::abs(DK); C2 = std::abs(DN); if (C1 < C2) { DMIN = C1; DMAX = C2; } else { DMIN = C2; DMAX = C1; } C4 = HK + HN; C3 = C4 + C4 + C4; C1 = (C4 + HK) / C3; C2 = (C4 + HN) / C3; C3 = DK / DMAX; C4 = DN / DMAX; MU = DMIN / (C1 * C3 + C2 * C4); } else MU = (DLReal) 0.0; } } /* Prepara i coefficienti calcolo spline */ C1 = (ML - DK) / HK; C2 = (MU - DK) / HK; C3 = -(C1 + C1 + C2); C4 = (C1 + C2) / HK; /* Estrae il punto massimo per l'intervallo funzione corrente */ IFU = XS - 1; IFL = IXP; while (IFU - IFL > 1) { IFP = (IFU + IFL) >> 1; if (X[IFP] > XNU) IFU = IFP; else IFL = IFP; } /* Aggiunge l'ultimo punto a fine spline */ if (ISU == N - 1) IFU++; /* Ciclo creazione valori spline */ while (IXP < IFU) { /* Rimappa X secondo l'intervallo corrente */ RX = X[IXP] - XNL; /* Imposta il valore nel punto */ Y[IXP] = YNL + RX * (ML + RX * (C3 + RX * C4)); /* Passa al punto successivo */ IXP++; } } } /* Interpolazione su scala lineare tramite B spline cubica uniforme con riparametrizzazione arc length tramite spline cubica Hermite monotonica */ Boolean AB3HSMSplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y) { /* Array gestione spline rimappatura */ DLReal * SX; DLReal * IX; /* Indice generico */ int I; /* Indice recupero monotonicit */ int XP; /* Alloca l'array interpolazione parametro */ if ((SX = new DLReal[XS]) == NULL) return(False); /* Interpolazione parametro */ AB3SplineValue(XN,XN,N,X,XS,SX); /* Estrae i soli valori monotonici */ XP = 0; Y[0] = X[0]; for (I = 1;I < XS;I++) if (SX[I] > SX[XP]) { XP++; SX[XP] = SX[I]; Y[XP] = X[I]; } XP++; /* Alloca l'array rimappatura parametro */ if ((IX = new DLReal[XS]) == NULL) { delete[] SX; return(False); } /* Rimappatura parametro */ APCHIPSplineValue(SX,Y,XP,X,XS,IX); /* Dealloca l'array interpolazione parametro */ delete[] SX; /* Interpolazione spline */ AB3SplineValue(XN,YN,N,IX,XS,Y); /* Dealloca l'array rimappatura parametro */ delete[] IX; /* Operazione completata */ return True; } /* Funzione generica interpolazione */ /* Nel caso si utilizzi un asse logaritmico i valori su tale asse devono essere strettamente maggiori di 0 */ Boolean CSLASplineValue(const DLReal * XN, const DLReal * YN, const int N, const DLReal * X, const int XS, DLReal * Y, const CSLSplineType SplineType, const CSLAxisType AxisType) { /* Indice generico */ int I; /* Array riferimento assi effettivi */ DLReal * XNE = NULL; DLReal * YNE = NULL; DLReal * XSE = NULL; /* Array preparazione spline */ DLReal * SPD2YNR; /* Valore di ritorno */ Boolean RV = True; /* Verifica il tipo di asse utilizzato */ switch (AxisType) { case CSLLinXLinY: /* Assegna gli assi di default */ XNE = (DLReal *) XN; YNE = (DLReal *) YN; XSE = (DLReal *) X; break; case CSLLogXLinY: /* Alloca l'array per l'asse X */ if ((XNE = new DLReal[N]) == NULL) return(False); if ((XSE = new DLReal[XS]) == NULL) { delete[] XNE; return(False); } /* Converte su scala logaritmica */ for (I = 0;I < N;I++) XNE[I] = (DLReal) log10(XN[I]); for (I = 0;I < XS;I++) XSE[I] = (DLReal) log10(X[I]); /* Assegna gli assi di default */ YNE = (DLReal *) YN; break; case CSLLinXLogY: /* Alloca l'array per l'asse Y */ if ((YNE = new DLReal[N]) == NULL) return(False); /* Converte su scala logaritmica */ for (I = 0;I < N;I++) YNE[I] = (DLReal) log10(YN[I]); /* Assegna gli assi di default */ XNE = (DLReal *) XN; XSE = (DLReal *) X; break; case CSLLogXLogY: /* Alloca l'array per l'asse X */ if ((XNE = new DLReal[N]) == NULL) return(False); if ((XSE = new DLReal[XS]) == NULL) { delete[] XNE; return(False); } /* Alloca l'array per l'asse Y */ if ((YNE = new DLReal[N]) == NULL) { delete[] XNE; delete[] XSE; return(False); } /* Converte su scala logaritmica */ for (I = 0;I < N;I++) XNE[I] = (DLReal) log10(XN[I]); for (I = 0;I < N;I++) YNE[I] = (DLReal) log10(YN[I]); for (I = 0;I < XS;I++) XSE[I] = (DLReal) log10(X[I]); break; } /* Verifica il tipo di interpolazione */ switch (SplineType) { /* Lineare */ case CSLLinear: AL1SplineValue(XNE,YNE,N,XSE,XS,Y); break; /* Spline cubica interpolante classica, classe C2, non monotonica */ case CSLCSpline: /* Alloca l'array preparazione spline */ if ((SPD2YNR = new DLReal[N]) == NULL) RV = False; else { /* Prepara le derivate spline */ if (SplinePrepare(XNE,YNE,N,(DLReal) 0.0,(DLReal) 0.0,SplineBNat,SPD2YNR) == False) { delete[] SPD2YNR; RV = False; } /* Calcola i valori spline */ ASplineValue(XNE,YNE,N,SPD2YNR,XSE,XS,Y); } break; /* B Spline cubica approssimante, classe C2, non interpolante */ case CSLBSpline: if (AB3HSMSplineValue(XNE,YNE,N,XSE,XS,Y) == False) RV = False; break; /* CatmullRom, interpolante, non monotonica */ case CSLCRSpline: AB3CRSplineValue(XNE,YNE,N,XSE,XS,Y); break; /* Hermite spline, interpolante, monotonica (PCHIP) */ case CSLHSSpline: APCHIPSplineValue(XNE,YNE,N,XSE,XS,Y); break; } /* Verifica il tipo di asse utilizzato */ switch (AxisType) { case CSLLinXLinY: /* Nessun array da deallocare */ break; case CSLLogXLinY: /* Dealloca gli array */ delete[] XNE; delete[] XSE; break; case CSLLinXLogY: /* Converte dalla scala logaritmica */ for (I = 0;I < XS;I++) Y[I] = (DLReal) pow(10,Y[I]); /* Dealloca gli array */ delete[] YNE; break; case CSLLogXLogY: /* Converte dalla scala logaritmica */ for (I = 0;I < XS;I++) Y[I] = (DLReal) pow(10,Y[I]); /* Dealloca gli array */ delete[] XNE; delete[] XSE; delete[] YNE; break; } /* Operazione completata */ return RV; } /* Funzione generica interpolazione, versione complessa */ /* Nel caso si utilizzi un asse logaritmico i valori di ampiezza su tale asse devono essere strettamente maggiori di 0. I valori di fase vengono sempre considerati su ascissa lineare */ Boolean CSLCASplineValue(const DLReal * XN, const DLReal * MN, const DLReal * PN, const int N, const DLReal * X, const int XS, DLComplex * Y, const CSLSplineType SplineType, const CSLAxisType AxisType) { /* Valori intermedi interpolazione */ DLReal * YV; /* Indice generico */ int I; /* Tipo asse fase */ CSLAxisType PAT = AxisType; /* Alloca l'array intermedio interpolazione */ if ((YV = new DLReal[XS]) == NULL) return(False); /* Effettua l'interpolazione dell'ampiezza */ if (CSLASplineValue(XN,MN,N,X,XS,YV,SplineType,AxisType) == False) { delete[] YV; return(False); } /* Assegna l'ampiezza */ for (I = 0;I < XS;I++) Y[I] = YV[I]; /* Imposta il tipo di asse per la fase */ switch (AxisType) { case CSLLinXLinY: case CSLLogXLinY: PAT = AxisType; break; case CSLLinXLogY: PAT = CSLLinXLinY; break; case CSLLogXLogY: PAT = CSLLogXLinY; break; } /* Effettua l'interpolazione sulla fase */ if (CSLASplineValue(XN,PN,N,X,XS,YV,SplineType,PAT) == False) { delete[] YV; return(False); } /* Assegna la fase */ for (I = 0;I < XS;I++) Y[I] = std::polar(Y[I].real(),YV[I]); /* Dealloca l'array intermedio */ delete[] YV; /* Operazione completata */ return True; } drc-3.2.2/source/bin/0000755000076400001450000000000013165107355013327 5ustar denisitadmdrc-3.2.2/source/convol.h0000644000076400001450000000571313162156312014230 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : Convol.h Autore : Sbragion Denis Descrizione : Funzioni per la convoluzione. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #ifndef Convol_h #define Convol_h #include "dsplib.h" // Effettua la convoluzione con il metodo diretto degli array A e B. // Il risultato viene posto in R che deve essere di lunghezza NA+NB-1. void Convolve(const DLReal * A,unsigned int NA,const DLReal * B, unsigned int NB,DLReal * R); void Convolve(const DLComplex * A,unsigned int NA,const DLComplex * B, unsigned int NB,DLComplex * R); // Effettua la convoluzione usando l' Fft col metodo diretto. // Questo sistema puo`, in alcunni casi, risultare piu` veloce del // metodo standard. // Richiede l' allocazione di array temporanei e ritorna False in // caso di memoria insufficiente. Boolean DFftConvolve(const DLReal * A,unsigned int NA,const DLReal * B, unsigned int NB,DLReal * R,DLComplex * CA = NULL,DLComplex * CB = NULL); Boolean DFftConvolve(const DLComplex * A,unsigned int NA,const DLComplex * B, unsigned int NB, DLComplex * R,DLComplex * CA = NULL,DLComplex * CB = NULL); // Effettua la convoluzione usando l' Fft col metodo overlap-add. // Questo sistema puo`, in alcunni casi, risultare piu` veloce del // metodo standard. // Richiede l' allocazione di array temporanei e ritorna False in // caso di memoria insufficiente. Boolean OAFftConvolve(const DLReal * A,unsigned int NA,const DLReal * B, unsigned int NB,DLReal * R,DLComplex * CA = NULL,DLComplex * CB = NULL); Boolean OAFftConvolve(const DLComplex * A,unsigned int NA,const DLComplex * B, unsigned int NB,DLComplex * R,DLComplex * CA = NULL,DLComplex * CB = NULL); #endif /***************************************************************************/ drc-3.2.2/source/config/0000755000076400001450000000000013165107356014025 5ustar denisitadmdrc-3.2.2/source/config/48.0 kHz/0000755000076400001450000000000013165107356015133 5ustar denisitadmdrc-3.2.2/source/config/48.0 kHz/normal-48.0.drc0000644000076400001450000001053611751752345017514 0ustar denisitadm# Normal correction settings # Normal prefiltering windows (500 ms at 20 Hz, 100 ms at 100 Hz, 10 ms at 1 kHz, 0.50 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Normal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 48000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 48 MPLowerWindow = 48000 # 500 ms MPUpperWindow = 48 # 0.5 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 48000 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 48 EPLowerWindow = 2044 # 21.3 ms EPUpperWindow = 48 # 0.5 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2044 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1022 ISPEUpperWindow = 766 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 28800 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 48 RTLowerWindow = 48000 # 500 ms RTUpperWindow = 48 # 0.5 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 48000 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-48.0.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1022 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/48.0 kHz/insane-48.0.drc0000644000076400001450000001065311751752344017500 0ustar denisitadm# Insane correction settings # Used only to show the effect of correction artifacts # Excessive prefiltering windows (1486 ms at 20 Hz, 295 ms at 100 Hz, 29.5 at 1 kHz, 1.50 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 48000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 196608 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 142 MPLowerWindow = 142656 # 1486 ms MPUpperWindow = 142 # 1.50 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 142656 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 142 EPLowerWindow = 5942 # 61.9 ms EPUpperWindow = 142 # 1.50 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 5942 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2971 ISPEUpperWindow = 2228 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 28800 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 142 RTLowerWindow = 142656 # 1486 ms RTUpperWindow = 142 # 1.50 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 142656 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-48.0.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 2971 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/48.0 kHz/erb-48.0.drc0000644000076400001450000001115511751752346016773 0ustar denisitadm# ERB scale approximation correction settings # The approximation is pretty accurate # The approximation has been computed considering: # df * dt = 2 # i.e. four time the Gabor limit. This is an estimation # of the real resolution achieved by the frequency # dependent windowing applied. # ERB appoximation windowind (65 ms at 20 Hz, 48.5 ms at 100 Hz, 12.6 ms at 1 kHz, 0.46 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # ERB approximation ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 48000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 44 MPLowerWindow = 6240 # 65 ms MPUpperWindow = 44 # 0.46 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.87 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 6240 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 44 EPLowerWindow = 2208 # 21.3 ms EPUpperWindow = 44 # 0.46 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2208 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1104 ISPEUpperWindow = 828 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 28800 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 44 RTLowerWindow = 6240 # 65 ms RTUpperWindow = 44 # 0.46 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.87 RTOutWindow = 6240 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-48.0.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1104 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/48.0 kHz/extreme-48.0.drc0000644000076400001450000001054611751752344017675 0ustar denisitadm# Extreme correction settings # Huge prefiltering windows (740 ms at 20 Hz, 147 ms at 100 Hz, 14.5 ms at 1 kHz, 0.74 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 48000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 71 MPLowerWindow = 71040 # 740 ms MPUpperWindow = 71 # 0.74 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 71040 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 71 EPLowerWindow = 2976 # 31.0 ms EPUpperWindow = 71 # 0.74 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2976 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1488 ISPEUpperWindow = 1116 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 28800 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 71 RTLowerWindow = 71040 # 740 ms RTUpperWindow = 71 # 0.74 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 71040 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-48.0.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1488 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/48.0 kHz/soft-48.0.drc0000644000076400001450000001053711751752347017202 0ustar denisitadm# Soft correction settings # Short prefiltering windows (370 ms at 20 Hz, 74.0 ms at 100 Hz, 7.38 ms at 1 kHz, 0.36 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 48000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 34 MPLowerWindow = 35520 # 370 ms MPUpperWindow = 34 # 0.36 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 35520 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 34 EPLowerWindow = 1488 # 15.5 ms EPUpperWindow = 34 # 0.36 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1488 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 744 ISPEUpperWindow = 558 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 28800 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 34 RTLowerWindow = 35520 # 370 ms RTUpperWindow = 34 # 0.36 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 35520 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-48.0.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 744 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/48.0 kHz/minimal-48.0.drc0000644000076400001450000001054211751752343017645 0ustar denisitadm# Minimal correction settings # Minimal prefiltering windows (250 ms at 20 Hz, 50.0 ms at 100 Hz, 5.00 ms at 1 kHz, 0.25 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 48000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 24 MPLowerWindow = 24000 # 250 ms MPUpperWindow = 24 # 0.25 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 24000 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 24 EPLowerWindow = 998 # 10.4 ms EPUpperWindow = 24 # 0.25 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 998 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 499 ISPEUpperWindow = 374 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 28800 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 24 RTLowerWindow = 24000 # 250 ms RTUpperWindow = 24 # 0.25 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 24000 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-48.0.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 499 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/48.0 kHz/strong-48.0.drc0000644000076400001450000001053511751752343017535 0ustar denisitadm# Strong correction settings # Wide prefiltering windows (544 ms at 20 Hz, 108 ms at 100 Hz, 10.8 ms at 1 kHz, 0.54 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Soft pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Soft ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 48000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 52 MPLowerWindow = 52224 # 544 ms MPUpperWindow = 52 # 0.54 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 52224 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 52 EPLowerWindow = 2178 # 22.7 ms EPUpperWindow = 52 # 0.54 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2178 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1089 ISPEUpperWindow = 817 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 28800 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 52 RTLowerWindow = 52224 # 544 ms RTUpperWindow = 52 # 0.54 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 52224 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-48.0.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1089 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/96.0 kHz/0000755000076400001450000000000013165107356015136 5ustar denisitadmdrc-3.2.2/source/config/96.0 kHz/strong-96.0.drc0000644000076400001450000001056011751752337017544 0ustar denisitadm# Strong correction settings # Wide prefiltering windows (544 ms at 20 Hz, 108 ms at 100 Hz, 10.8 ms at 1 kHz, 0.54 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Soft pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Soft ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 96000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 104 MPLowerWindow = 104448 # 544 ms MPUpperWindow = 104 # 0.54 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 104448 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 104 EPLowerWindow = 4356 # 22.7 ms EPUpperWindow = 104 # 0.54 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 4356 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2178 ISPEUpperWindow = 1634 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 57600 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 104 RTLowerWindow = 104448 # 544 ms RTUpperWindow = 104 # 0.54 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 104448 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-96.0.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 2178 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/96.0 kHz/insane-96.0.drc0000644000076400001450000001066311751752340017503 0ustar denisitadm# Insane correction settings # Used only to show the effect of correction artifacts # Excessive prefiltering windows (1486 ms at 20 Hz, 295 ms at 100 Hz, 29.5 at 1 kHz, 1.50 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 96000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 393216 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 284 MPLowerWindow = 285312 # 1486 ms MPUpperWindow = 284 # 1.50 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 285312 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 282 EPLowerWindow = 5942 # 61.9 ms EPUpperWindow = 282 # 1.50 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 5942 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 5942 ISPEUpperWindow = 4456 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 57600 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 284 RTLowerWindow = 285312 # 1486 ms RTUpperWindow = 284 # 1.50 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 285312 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-96.0.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 5942 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/96.0 kHz/extreme-96.0.drc0000644000076400001450000001057011751752341017675 0ustar denisitadm# Extreme correction settings # Huge prefiltering windows (740 ms at 20 Hz, 147 ms at 100 Hz, 14.5 ms at 1 kHz, 0.74 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 96000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 142 MPLowerWindow = 142080 # 740 ms MPUpperWindow = 142 # 0.74 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 142080 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 142 EPLowerWindow = 5952 # 31.0 ms EPUpperWindow = 142 # 0.74 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 5952 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2976 ISPEUpperWindow = 2232 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 57600 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 142 RTLowerWindow = 142080 # 740 ms RTUpperWindow = 142 # 0.74 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 142080 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-96.0.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 2976 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/96.0 kHz/minimal-96.0.drc0000644000076400001450000001055411751752342017655 0ustar denisitadm# Minimal correction settings # Minimal prefiltering windows (250 ms at 20 Hz, 50.0 ms at 100 Hz, 5.00 ms at 1 kHz, 0.25 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 96000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 48 MPLowerWindow = 48000 # 250 ms MPUpperWindow = 48 # 0.25 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 48000 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 48 EPLowerWindow = 1996 # 10.4 ms EPUpperWindow = 48 # 0.25 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1996 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 998 ISPEUpperWindow = 748 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 57600 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 48 RTLowerWindow = 48000 # 250 ms RTUpperWindow = 48 # 0.25 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 48000 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-96.0.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 998 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/96.0 kHz/erb-96.0.drc0000644000076400001450000001117211751752336016777 0ustar denisitadm# ERB scale approximation correction settings # The approximation is pretty accurate # The approximation has been computed considering: # df * dt = 2 # i.e. four time the Gabor limit. This is an estimation # of the real resolution achieved by the frequency # dependent windowing applied. # ERB appoximation windowind (65 ms at 20 Hz, 48.5 ms at 100 Hz, 12.6 ms at 1 kHz, 0.46 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # ERB approximation ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 96000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 88 MPLowerWindow = 12480 # 65 ms MPUpperWindow = 88 # 0.46 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.87 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 12480 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 88 EPLowerWindow = 4416 # 21.3 ms EPUpperWindow = 88 # 0.46 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 4416 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2208 ISPEUpperWindow = 1656 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 57600 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 88 RTLowerWindow = 12480 # 65 ms RTUpperWindow = 88 # 0.46 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.87 RTOutWindow = 12480 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-96.0.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 2208 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/96.0 kHz/normal-96.0.drc0000644000076400001450000001054711751752340017517 0ustar denisitadm# Normal correction settings # Normal prefiltering windows (500 ms at 20 Hz, 100 ms at 100 Hz, 10 ms at 1 kHz, 0.50 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Normal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 96000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 96 MPLowerWindow = 96000 # 500 ms MPUpperWindow = 96 # 0.5 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 96000 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 96 EPLowerWindow = 4088 # 21.3 ms EPUpperWindow = 96 # 0.5 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 4088 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2044 ISPEUpperWindow = 1533 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 57600 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 96 RTLowerWindow = 96000 # 500 ms RTUpperWindow = 96 # 0.5 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 96000 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-96.0.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 2044 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/96.0 kHz/soft-96.0.drc0000644000076400001450000001055211751752335017202 0ustar denisitadm# Soft correction settings # Short prefiltering windows (370 ms at 20 Hz, 74.0 ms at 100 Hz, 7.38 ms at 1 kHz, 0.36 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 96000 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 68 MPLowerWindow = 71040 # 370 ms MPUpperWindow = 68 # 0.36 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 71040 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 68 EPLowerWindow = 2976 # 15.5 ms EPUpperWindow = 68 # 0.36 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2976 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1488 ISPEUpperWindow = 1116 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 57600 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 68 RTLowerWindow = 71040 # 370 ms RTUpperWindow = 68 # 0.36 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 71040 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-96.0.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 1488 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/44.1 kHz/0000755000076400001450000000000013165107356015130 5ustar denisitadmdrc-3.2.2/source/config/44.1 kHz/erb-44.1.drc0000644000076400001450000001115311751752333016757 0ustar denisitadm# ERB scale approximation correction settings # The approximation is pretty accurate # The approximation has been computed considering: # df * dt = 2 # i.e. four time the Gabor limit. This is an estimation # of the real resolution achieved by the frequency # dependent windowing applied. # ERB appoximation windowind (65 ms at 20 Hz, 48.5 ms at 100 Hz, 12.6 ms at 1 kHz, 0.46 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # ERB approximation ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 40 MPLowerWindow = 5734 # 65 ms MPUpperWindow = 40 # 0.46 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.87 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 5734 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 40 EPLowerWindow = 1836 # 21.3 ms EPUpperWindow = 40 # 0.46 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1836 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 918 ISPEUpperWindow = 688 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 40 RTLowerWindow = 5734 # 65 ms RTUpperWindow = 40 # 0.46 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.87 RTOutWindow = 5734 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 918 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/44.1 kHz/strong-44.1.drc0000644000076400001450000001053511751752333017526 0ustar denisitadm# Strong correction settings # Wide prefiltering windows (544 ms at 20 Hz, 108 ms at 100 Hz, 10.8 ms at 1 kHz, 0.54 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Soft pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Soft ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 48 MPLowerWindow = 48000 # 544 ms MPUpperWindow = 48 # 0.54 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 48000 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 48 EPLowerWindow = 2000 # 22.7 ms EPUpperWindow = 48 # 0.54 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2000 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1000 ISPEUpperWindow = 750 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 48 RTLowerWindow = 48000 # 544 ms RTUpperWindow = 48 # 0.54 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 48000 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1000 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/44.1 kHz/minimal-44.1.drc0000644000076400001450000001054211751752333017636 0ustar denisitadm# Minimal correction settings # Minimal prefiltering windows (250 ms at 20 Hz, 50.0 ms at 100 Hz, 5.00 ms at 1 kHz, 0.25 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 22 MPLowerWindow = 22050 # 250 ms MPUpperWindow = 22 # 0.25 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 22050 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 22 EPLowerWindow = 918 # 10.4 ms EPUpperWindow = 22 # 0.25 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 918 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 459 ISPEUpperWindow = 344 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 22 RTLowerWindow = 22050 # 250 ms RTUpperWindow = 22 # 0.25 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 22050 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 459 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/44.1 kHz/normal-44.1.drc0000644000076400001450000001053411751752334017502 0ustar denisitadm# Normal correction settings # Normal prefiltering windows (500 ms at 20 Hz, 100 ms at 100 Hz, 10 ms at 1 kHz, 0.50 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Normal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 44 MPLowerWindow = 44100 # 500 ms MPUpperWindow = 44 # 0.5 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 44100 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 44 EPLowerWindow = 1836 # 20.8 ms EPUpperWindow = 44 # 0.5 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1836 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 918 ISPEUpperWindow = 688 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 44 RTLowerWindow = 44100 # 500 ms RTUpperWindow = 44 # 0.5 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 44100 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 918 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/44.1 kHz/extreme-44.1.drc0000644000076400001450000001054611751752333017665 0ustar denisitadm# Extreme correction settings # Huge prefiltering windows (740 ms at 20 Hz, 147 ms at 100 Hz, 14.5 ms at 1 kHz, 0.74 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 64 MPLowerWindow = 65536 # 740 ms MPUpperWindow = 64 # 0.74 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 65536 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 64 EPLowerWindow = 2730 # 31.0 ms EPUpperWindow = 64 # 0.74 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2730 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1365 ISPEUpperWindow = 1024 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 64 RTLowerWindow = 65536 # 740 ms RTUpperWindow = 64 # 0.74 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 65536 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1365 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/44.1 kHz/insane-44.1.drc0000644000076400001450000001065311751752334017471 0ustar denisitadm# Insane correction settings # Used only to show the effect of correction artifacts # Excessive prefiltering windows (1486 ms at 20 Hz, 295 ms at 100 Hz, 29.5 at 1 kHz, 1.50 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 132 MPLowerWindow = 131072 # 1486 ms MPUpperWindow = 132 # 1.50 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 131072 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 132 EPLowerWindow = 5460 # 61.9 ms EPUpperWindow = 132 # 1.50 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 5460 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2730 ISPEUpperWindow = 2048 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 132 RTLowerWindow = 131072 # 1486 ms RTUpperWindow = 132 # 1.50 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 131072 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 2730 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/44.1 kHz/soft-44.1.drc0000644000076400001450000001053711751752333017167 0ustar denisitadm# Soft correction settings # Short prefiltering windows (370 ms at 20 Hz, 74.0 ms at 100 Hz, 7.38 ms at 1 kHz, 0.36 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 32 MPLowerWindow = 32768 # 370 ms MPUpperWindow = 32 # 0.36 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 32768 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 32 EPLowerWindow = 1366 # 15.5 ms EPUpperWindow = 32 # 0.36 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1366 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 683 ISPEUpperWindow = 512 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 32 RTLowerWindow = 32768 # 370 ms RTUpperWindow = 32 # 0.36 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 32768 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 683 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/88.2 kHz/0000755000076400001450000000000013165107355015140 5ustar denisitadmdrc-3.2.2/source/config/88.2 kHz/minimal-88.2.drc0000644000076400001450000001055411751752330017660 0ustar denisitadm# Minimal correction settings # Minimal prefiltering windows (250 ms at 20 Hz, 50.0 ms at 100 Hz, 5.00 ms at 1 kHz, 0.25 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 88200 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 44 MPLowerWindow = 44100 # 250 ms MPUpperWindow = 44 # 0.25 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 44100 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 44 EPLowerWindow = 1836 # 10.4 ms EPUpperWindow = 44 # 0.25 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1836 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 918 ISPEUpperWindow = 688 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 52920 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 44 RTLowerWindow = 44100 # 250 ms RTUpperWindow = 44 # 0.25 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 44100 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-88.2.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 918 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/88.2 kHz/insane-88.2.drc0000644000076400001450000001066511751752333017515 0ustar denisitadm# Insane correction settings # Used only to show the effect of correction artifacts # Excessive prefiltering windows (1486 ms at 20 Hz, 295 ms at 100 Hz, 29.5 at 1 kHz, 1.50 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 88200 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 262 MPLowerWindow = 262144 # 1486 ms MPUpperWindow = 262 # 1.50 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 262144 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 262 EPLowerWindow = 10920 # 61.9 ms EPUpperWindow = 262 # 1.50 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 10920 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 5460 ISPEUpperWindow = 4096 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 52920 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 262 RTLowerWindow = 262144 # 1486 ms RTUpperWindow = 262 # 1.50 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 131072 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-88.2.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 5460 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/88.2 kHz/normal-88.2.drc0000644000076400001450000001054711751752331017525 0ustar denisitadm# Normal correction settings # Normal prefiltering windows (500 ms at 20 Hz, 100 ms at 100 Hz, 10 ms at 1 kHz, 0.50 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Normal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 88200 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 88 MPLowerWindow = 88200 # 500 ms MPUpperWindow = 88 # 0.5 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 88200 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 88 EPLowerWindow = 3672 # 21.3 ms EPUpperWindow = 88 # 0.5 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 3672 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1836 ISPEUpperWindow = 1377 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 52920 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 88 RTLowerWindow = 88200 # 500 ms RTUpperWindow = 88 # 0.5 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 88200 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-88.2.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 1836 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/88.2 kHz/soft-88.2.drc0000644000076400001450000001055211751752327017211 0ustar denisitadm# Soft correction settings # Short prefiltering windows (370 ms at 20 Hz, 74.0 ms at 100 Hz, 7.38 ms at 1 kHz, 0.36 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 88200 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 64 MPLowerWindow = 65536 # 370 ms MPUpperWindow = 64 # 0.36 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 65536 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 64 EPLowerWindow = 2732 # 15.5 ms EPUpperWindow = 64 # 0.36 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2732 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1366 ISPEUpperWindow = 1024 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 52920 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 64 RTLowerWindow = 65536 # 370 ms RTUpperWindow = 64 # 0.36 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 65536 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-88.2.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 1366 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/88.2 kHz/extreme-88.2.drc0000644000076400001450000001057011751752332017703 0ustar denisitadm# Extreme correction settings # Huge prefiltering windows (740 ms at 20 Hz, 147 ms at 100 Hz, 14.5 ms at 1 kHz, 0.74 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 88200 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 128 MPLowerWindow = 131072 # 740 ms MPUpperWindow = 128 # 0.74 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 131072 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 128 EPLowerWindow = 5460 # 31.0 ms EPUpperWindow = 128 # 0.74 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 5460 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2730 ISPEUpperWindow = 2048 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 52920 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 128 RTLowerWindow = 131072 # 740 ms RTUpperWindow = 128 # 0.74 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 131072 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-88.2.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 2730 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/88.2 kHz/erb-88.2.drc0000644000076400001450000001117211751752326017004 0ustar denisitadm# ERB scale approximation correction settings # The approximation is pretty accurate # The approximation has been computed considering: # df * dt = 2 # i.e. four time the Gabor limit. This is an estimation # of the real resolution achieved by the frequency # dependent windowing applied. # ERB appoximation windowind (65 ms at 20 Hz, 48.5 ms at 100 Hz, 12.6 ms at 1 kHz, 0.46 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # ERB approximation ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 88200 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 80 MPLowerWindow = 11468 # 65 ms MPUpperWindow = 80 # 0.46 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.87 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 11468 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 80 EPLowerWindow = 3672 # 21.3 ms EPUpperWindow = 80 # 0.46 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 3672 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1836 ISPEUpperWindow = 1377 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 52920 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 80 RTLowerWindow = 11468 # 65 ms RTUpperWindow = 80 # 0.46 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.87 RTOutWindow = 11468 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-88.2.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 1836 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/config/88.2 kHz/strong-88.2.drc0000644000076400001450000001054611751752330017547 0ustar denisitadm# Strong correction settings # Wide prefiltering windows (544 ms at 20 Hz, 108 ms at 100 Hz, 10.8 ms at 1 kHz, 0.54 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Soft pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Soft ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 88200 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 262144 BCPreWindowLen = 2048 BCPreWindowGap = 1536 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 96 MPLowerWindow = 96000 # 544 ms MPUpperWindow = 96 # 0.54 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 131072 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 96000 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 96 EPLowerWindow = 4000 # 22.7 ms EPUpperWindow = 96 # 0.54 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 131072 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 4000 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2000 ISPEUpperWindow = 1500 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 16384 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 52920 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 96 RTLowerWindow = 96000 # 544 ms RTUpperWindow = 96 # 0.54 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 131072 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 96000 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 131071 PSNumPoints = 0 PSPointsFile = pa-88.2.txt PSMagType = D PSOutWindow = 131072 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 131072 MSFilterDelay = 2000 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/source/kirkebyfd.h0000644000076400001450000000653013162156312014700 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Inversione tramite Kirkeby fast deconvolution */ #ifndef KirkebyFD_h #define KirkebyFD_h /* Inclusioni */ #include "dsplib.h" #include "slprefilt.h" /* Inversione tramite Kirkeby fast deconvolution */ Boolean KirkebyFDInvert(const DLReal * InSig, int InSigLen,DLReal * InvFilter, int InvFilterLen, const DLReal * EffortSig, int EffortSigLen, DLReal EffortFactor, int MExp); /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a misura indiretta degli effetti di pre echo */ Boolean PEISMPKirkebyFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, DLReal EffortFactor, int MExp); /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a misura diretta degli effetti di pre echo */ Boolean PEMSMPKirkebyFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, DLReal EffortFactor, int PEStart, int PETransition, int MExp); /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a troncatura degli effetti di pre echo */ Boolean PETFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, char PEType, int PELowerWindow, int PEUpperWindow, DLReal PEStartFreq, DLReal PEEndFreq, int PEFilterLen, DLReal FSharpness, int PEBandSplit, DLReal PEWindowExponent, const SLPPrefilteringType SLPType, const DLReal OGainFactor, int SampleRate, int MExp); /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a troncatura multipla degli effetti di pre echo con componente EP di riferimento */ Boolean MRefPETFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, char PEType, int PELowerWindow, int PEUpperWindow, DLReal PEStartFreq, DLReal PEEndFreq, int PEFilterLen, DLReal FSharpness, int PEBandSplit, DLReal PEWindowExponent, const SLPPrefilteringType SLPType, const DLReal * EPRef, int EPRefLen, char RPEType, int RPELowerWindow, int RPEUpperWindow, DLReal RPEStartFreq, DLReal RPEEndFreq, int RPEFilterLen, DLReal RFSharpness, int RPEBandSplit, DLReal RPEWindowExponent, const SLPPrefilteringType RSLPType, const DLReal OGainFactor, int SampleRate, int MExp); #endif drc-3.2.2/source/lsconv.depend0000644000076400001450000000154013164707351015245 0ustar denisitadm# depslib dependency file v1.0 1125668174 d:\denis\drc\lsconv.c "fftsg_h.h" 1117804148 d:\denis\drc\fftsg_h.h 1117804148 d:\denis\drc\fftsg_h.c "fftsg_h.h" 1134661926 source:i:\varie\room\drc\lsconv.c "fftsg_h.h" 1134661926 i:\varie\room\drc\fftsg_h.h 1134661926 source:i:\varie\room\drc\fftsg_h.c "fftsg_h.h" 1134665526 source:i:\varie\drc\fftsg_h.c "fftsg_h.h" 1262690798 i:\varie\drc\fftsg_h.h 1322753167 source:i:\varie\drc\lsconv.c "fftsg_h.h" drc-3.2.2/source/glsweep.c0000644000076400001450000002260313164706506014376 0ustar denisitadm/**************************************************************************** DRC: Digital Room Correction Copyright (C) 2002-2004 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@neomerica.it ****************************************************************************/ /* Log sweep and inverse filter generation program */ /* Derived from a perl script kindly provided by Edward Wildgoose */ /* Includes */ #include #include #include /* Decommentare per abilitare la compilazione in doppia precisione */ /* Uncomment to enable double precision computation */ #define UseDouble #ifdef UseDouble /* Tipo floating point usato per le elaborazioni */ #define DLReal double #else /* Tipo floating point usato per le elaborazioni */ #define DLReal float #endif /* Imposta l'uso delle funzioni trigonometriche ridotte */ #define UseTypedTrigs /* Verifica l'uso delle funzioni trigonometriche ridotte */ #ifdef UseTypedTrigs #ifdef UseDouble #define DLSin sin #define DLCos cos #define DLTan tan #define DLATan atan #else #define DLSin sinf #define DLCos cosf #define DLTan tanf #define DLATan atanf #endif #else #define DLSin sin #define DLCos cos #define DLTan tan #define DLATan atan #endif #ifndef M_PI #define M_PI ((DLReal) 3.14159265358979323846264338327950288) #endif #ifndef M_2PI #define M_2PI ((DLReal) 6.28318530717958647692528676655900576) #endif /* Output stringhe con sync output e parametro */ int sputsp(const char * s, const char * p) { int Res; if (p == NULL) Res = puts(s); else Res = printf("%s%s\n",s,p); fflush(stdout); return(Res); } /* Output stringhe con sync output */ int sputs(const char * s) { return(sputsp(s, NULL)); } /* Main procedure */ int main(int argc, char * argv[]) { /* Input parameters */ DLReal Rate; DLReal Amplitude; DLReal HzStart; DLReal HzEnd; DLReal Duration; DLReal Silence; DLReal LeadIn; DLReal LeadOut; char * SweepFile; char * InverseFile; /* Generation parameters */ /* Base sweep generation */ int SweepLen; int SilenceLen; DLReal W1; DLReal W2; DLReal Ratio; DLReal Sample; DLReal S1; DLReal S2; DLReal DecayTime; DLReal Decay; int I; int J; float FS; /* Sweep normalization factor */ DLReal SNF; /* Lead in and lead out Blackman windowing */ int LeadInLen; DLReal WC1In; DLReal WC2In; int LeadOutLen; DLReal WC1Out; DLReal WC2Out; DLReal WC; /* Output file */ FILE * OF; /* Initial message */ sputs("\nGLSweep 1.1.0: log sweep and inverse filter generation."); sputs("Copyright (C) 2002-2011 Denis Sbragion"); #ifdef UseDouble sputs("\nCompiled with double precision arithmetic."); #else sputs("\nCompiled with single precision arithmetic."); #endif sputs("\nThis program may be freely redistributed under the terms of"); sputs("the GNU GPL and is provided to you as is, without any warranty"); sputs("of any kind. Please read the file \"COPYING\" for details."); /* Check program arguments */ if (argc < 11) { sputs("\nUsage: glsweep rate amplitude hzstart hzend duration silence"); sputs(" leadin leadout sweepfile inversefile"); sputs("\nParameters:\n"); sputs(" rate: reference sample rate"); sputs(" amplitude: sweep amplitude"); sputs(" hzstart: sweep start frequency"); sputs(" hzend: sweep end frequency"); sputs(" duration: sweep duration in seconds"); sputs(" silence: leading and trailing silence duration in seconds"); sputs(" leadin: leading window length as a fraction of duration"); sputs(" leadout: trailing window length as a fraction of duration"); sputs(" sweepfile: sweep file name"); sputs(" inversefile: inverse sweep file name"); sputs("\nExample: glsweep 44100 0.5 10 21000 45 2 0.05 0.005 sweep.pcm inverse.pcm\n"); return 0; } /* Get the input parameters from the command line */ sputs("\nCommand line parsing."); Rate = (DLReal) atof(argv[1]); Amplitude = (DLReal) atof(argv[2]); HzStart = (DLReal) atof(argv[3]); HzEnd = (DLReal) atof(argv[4]); Duration = (DLReal) atof(argv[5]); Silence = (DLReal) atof(argv[6]); LeadIn = (DLReal) atof(argv[7]); LeadOut = (DLReal) atof(argv[8]); SweepFile = argv[9]; InverseFile = argv[10]; /* Computes internal generation values */ sputs("Sweep generation setup."); /* Base sweep generation */ SweepLen = (int) (Rate * Duration); SilenceLen = (int) (Rate * Silence); W1 = (DLReal) (HzStart * M_2PI); W2 = (DLReal) (HzEnd * M_2PI); Ratio = (DLReal) log(W2 / W1); S1 = (DLReal) ((W1 * Duration) / Ratio); S2 = (DLReal) (Ratio / SweepLen); DecayTime = (DLReal) (SweepLen * log(2.0) / Ratio); /* Lead in and lead out Blackman windowing */ LeadInLen = (int) (LeadIn * SweepLen); WC1In = (DLReal) M_PI / (LeadInLen - 1); WC2In = (DLReal) M_2PI / (LeadInLen - 1); LeadOutLen = (int) (LeadOut * SweepLen); WC1Out = (DLReal) M_PI / (LeadOutLen - 1); WC2Out = (DLReal) M_2PI / (LeadOutLen - 1); /* Report generation parameters */ printf("\nSweep length: %ld samples\n",(unsigned long int) SweepLen); printf("Silence length: %ld samples\n",(unsigned long int) SilenceLen); printf("Total sweep length: %ld samples\n",(unsigned long int) 2 * SilenceLen + SweepLen); printf("Total sweep file size: %ld bytes\n",(unsigned long int) sizeof(float) * (2 * SilenceLen + SweepLen)); printf("Total inverse length: %ld samples\n",(unsigned long int) SweepLen); printf("Total inverse file size: %ld bytes\n\n",(unsigned long int) sizeof(float) * SweepLen); fflush(stdout); /* Open the sweep file */ sputsp("Opening sweep file: ", SweepFile); if ((OF = fopen(SweepFile,"wb")) == NULL) { perror("Unable to open sweep file"); return 1; } /* Generates the sweep file */ sputs("Generating the sweep file..."); /* Initial silence */ FS = (DLReal) 0.0; for (I = 0;I < SilenceLen;I++) fwrite(&FS,sizeof(float),1,OF); /* Initial lead in */ for (I = 0;I < LeadInLen;I++) { Sample = (DLReal) DLSin(S1 * (exp(I * S2) - 1.0)); WC = (DLReal) (0.42 - 0.5 * DLCos(WC1In * I) + 0.08 * DLCos(WC2In * I)); FS = (float) (Sample * WC * Amplitude); fwrite(&FS,sizeof(float),1,OF); } /* Full sweep */ for (I = LeadInLen;I < SweepLen - LeadOutLen;I++) { Sample = (DLReal) DLSin(S1 * (exp(I * S2) - 1.0)); FS = (float) (Sample * Amplitude); fwrite(&FS,sizeof(float),1,OF); } /* Final lead out */ for (I = SweepLen - LeadOutLen,J = LeadOutLen;I < SweepLen;I++,J--) { Sample = (DLReal) DLSin(S1 * (exp(I * S2) - 1.0)); WC = (DLReal) (0.42 - 0.5 * DLCos(WC1Out * J) + 0.08 * DLCos(WC2Out * J)); FS = (float) (Sample * WC * Amplitude); fwrite(&FS,sizeof(float),1,OF); } /* Final silence */ FS = (DLReal) 0.0; for (I = 0;I < SilenceLen;I++) fwrite(&FS,sizeof(float),1,OF); /* Close the sweep file */ sputs("Sweep file generated."); fclose(OF); /* Computes the sweep normalization factor */ /* Number of octaves involved */ SNF = (DLReal) (log(HzEnd/HzStart) / log(2.0)); /* Bandwidth and exponential decay compensation */ SNF = (DLReal) ((2.0 * (HzEnd - HzStart) / Rate) * (log(4.0) * SNF / (1 - pow(2.0,-SNF))) / SweepLen); /* Report the normalization factor */ printf("Sweep normalizaton factor: %g\n",SNF); fflush(stdout); /* Open the inverse file */ sputsp("Opening inverse file: ", InverseFile); if ((OF = fopen(InverseFile,"wb")) == NULL) { perror("Unable to open inverse file"); return 1; } /* Generates the sweep file */ sputs("Generating the inverse file..."); /* Final lead out */ for (I = 0,J = SweepLen;I < LeadOutLen;I++,J--) { Decay = (DLReal) pow(0.5,I / DecayTime); Sample = (DLReal) DLSin(S1 * (exp(J * S2) - 1.0)); WC = (DLReal) (0.42 - 0.5 * DLCos(WC1Out * I) + 0.08 * DLCos(WC2Out * I)); FS = (float) (SNF * Sample * WC * Decay); fwrite(&FS,sizeof(float),1,OF); } /* Full sweep */ for (I = LeadOutLen,J = SweepLen - LeadOutLen;I < SweepLen - LeadInLen;I++,J--) { Decay = (DLReal) pow(0.5,I / DecayTime); Sample = (DLReal) DLSin(S1 * (exp(J * S2) - 1.0)); FS = (float) (SNF * Sample * Decay); fwrite(&FS,sizeof(float),1,OF); } /* Initial lead in */ for (I = SweepLen - LeadInLen,J = LeadInLen;I < SweepLen;I++,J--) { Decay = (DLReal) pow(0.5,I / DecayTime); Sample = (DLReal) DLSin(S1 * (exp(J * S2) - 1.0)); WC = (DLReal) (0.42 - 0.5 * DLCos(WC1In * J) + 0.08 * DLCos(WC2In * J)); FS = (float) (SNF * Sample * WC * Decay); fwrite(&FS,sizeof(float),1,OF); } /* Close the inverse file */ sputs("Inverse file generated."); fclose(OF); /* Execution completed */ return 0; } drc-3.2.2/source/kirkebyfd.cpp0000644000076400001450000006552313165106440015242 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Inclusioni */ #include "kirkebyfd.h" #include "fft.h" #include "baselib.h" #include "level.h" #include "hd.h" #include "dspwind.h" #include "slprefilt.h" #include "bwprefilt.h" #include "convol.h" #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif /* Inversione tramite Kirkeby fast deconvolution */ Boolean KirkebyFDInvert(const DLReal * InSig, int InSigLen,DLReal * InvFilter, int InvFilterLen, const DLReal * EffortSig, int EffortSigLen, DLReal EffortFactor, int MExp) { /* Dimensione da considerare per il segnale */ int SigLen; /* Dimensione FFT */ int FS; /* Array FFT */ DLComplex * FFTArray1; DLComplex * FFTArray2 = NULL; /* Livello RMS segnale in ingresso */ DLReal IRMS; /* Livello massimo del segnale di effort */ DLReal EMax; /* Indice generico */ int I = 0; int J = 0; /* Determina la dimensione massima tra i vari segnali */ if (InSigLen > InvFilterLen) SigLen = InSigLen; else SigLen = InvFilterLen; if (EffortSig != NULL) if (EffortSigLen > SigLen) SigLen = EffortSigLen; /* Controlla se si deve adottare un potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if (EffortSig != NULL) if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < InSigLen;I++) FFTArray1[I] = InSig[I]; /* Azzera la parte rimanente */ for (I = InSigLen;I < FS;I++) FFTArray1[I] = 0; if (EffortSig != NULL) { /* Copia l'array effort in quello temporaneo */ for (I = 0;I < EffortSigLen;I++) FFTArray2[I] = EffortSig[I]; /* Azzera la parte rimanente */ for (I = EffortSigLen;I < FS;I++) FFTArray2[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Calcola il valore massimo dell'array effort */ EMax = 0; for (I = 0;I < FS;I++) if (std::abs(FFTArray2[I]) > EMax) EMax = std::abs(FFTArray2[I]); EMax *= EMax; /* Riscala il fattore di effort */ EffortFactor /= EMax; } /* Porta nel dominio della frequenza */ Fft(FFTArray1,FS); /* Calcola il livello RMS del segnale in ingresso */ IRMS = GetRMSLevel(InSig,InSigLen); /* Riscala il fattore di effort */ EffortFactor *= IRMS * IRMS; /* Effettua la fast deconvolution */ if (EffortSig != NULL) { for (I = 0;I < FS;I++) FFTArray1[I] = std::conj(FFTArray1[I]) / (FFTArray1[I] * std::conj(FFTArray1[I]) + EffortFactor * (EMax - FFTArray2[I] * std::conj(FFTArray2[I]))); } else { for (I = 0;I < FS;I++) FFTArray1[I] = std::conj(FFTArray1[I]) / (FFTArray1[I] * std::conj(FFTArray1[I]) + EffortFactor); } /* Ritorna nel dominio del tempo */ IFft(FFTArray1,FS); /* Estrae il filtro inverso */ for (I = 0,J = (FS + FS - (InSigLen - InvFilterLen) / 2) % FS;I < InvFilterLen;I++,J = (J + 1) % FS) InvFilter[I] = std::real(FFTArray1[J]); /* Dealloca gli array temporanei */ delete[] FFTArray1; if (EffortSig != NULL) delete[] FFTArray2; /* Operazione completata */ return True; } /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a misura indiretta degli effetti di pre echo */ Boolean PEISMPKirkebyFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, DLReal EffortFactor, int MExp) { /* Dimensione da considerare per il segnale */ int SigLen; /* Dimensione FFT */ int FS; /* Array FFT */ DLComplex * FFTArray1; DLComplex * FFTArray2; /* Valore massimo e minimo componente EP */ DLReal * AEPAbs; DLReal EPAbs; DLReal EMax; /* Indici generici */ int I; int J; /* Determina la dimensione massima tra i vari segnali */ if (MPSigLen > InvFilterLen) SigLen = MPSigLen; else SigLen = InvFilterLen; if (EPSigLen > SigLen) SigLen = EPSigLen; /* Controlla se si deve adottare una potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < MPSigLen;I++) FFTArray1[I] = MPSig[I]; /* Azzera la parte rimanente */ for (I = MPSigLen;I < FS;I++) FFTArray1[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray1,FS); /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < EPSigLen;I++) FFTArray2[I] = EPSig[I]; /* Azzera la parte rimanente */ for (I = EPSigLen;I < FS;I++) FFTArray2[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Alloca l' array per l'ampiezza EP */ if ((AEPAbs = new DLReal[FS]) == NULL) return False; /* Estrae l'array valori assoluti */ for (I = 0;I < FS;I++) AEPAbs[I] = std::abs(FFTArray2[I]); /* Calcola il valore massimo della componente EP */ EMax = 0; for (I = 0;I < FS;I++) { if (AEPAbs[I] > EMax) EMax = AEPAbs[I]; } /* Riscala il fattore di effort */ if (EffortFactor >= 0) EffortFactor = -EffortFactor / ((DLReal) 1.0 + EffortFactor); else EffortFactor = EffortFactor / (EffortFactor - (DLReal) 1.0); /* Effettua la fast deconvolution selettiva della componente EP */ for (I = 0;I < FS;I++) { /* Normalizza il valore assoluto */ EPAbs = AEPAbs[I] / EMax; /* Applica il fattore di effort controllando eventuali singolarit */ if (EPAbs <= (DLReal) 0.0) EPAbs = (DLReal) 0.0; else if (EPAbs >= (DLReal) 1.0) EPAbs = (DLReal) 1.0; else { EPAbs = sqrt(EPAbs); EPAbs = (EPAbs * ((DLReal) 1.0 + EffortFactor)) / ((DLReal) 1.0 + EPAbs * EffortFactor); } /* Calcola la trasformata della deconvoluzione selettiva */ FFTArray2[I] = std::polar(EPAbs,-std::arg(FFTArray2[I])) + std::polar((DLReal) 1.0 - EPAbs,(I * M_PI * EPSigLen) / FS); } /* Dealloca gli array temporanei */ delete[] AEPAbs; /* Compone l'inverso componente MP e EP */ for (I = 0;I < FS;I++) FFTArray1[I] = std::polar(1,std::arg(FFTArray2[I])) / FFTArray1[I]; /* Ritorna nel dominio del tempo */ IFft(FFTArray1,FS); /* Estrae il filtro inverso */ for (I = 0,J = (1 + FS + FS - (MPSigLen + EPSigLen + InvFilterLen) / 2) % FS;I < InvFilterLen;I++,J = (J + 1) % FS) InvFilter[I] = std::real(FFTArray1[J]); /* Dealloca gli array temporanei */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a misura diretta degli effetti di pre echo */ Boolean PEMSMPKirkebyFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, DLReal EffortFactor, int PEStart, int PETransition, int MExp) { /* Dimensione da considerare per il segnale */ int SigLen; /* Dimensione FFT */ int FS; /* Array FFT */ DLComplex * FFTArray1; DLComplex * FFTArray2; /* Valore massimo e minimo componente EP */ DLReal * AEPAbs; DLReal EPAbs; DLReal EMax; /* Indici generici */ int I; int J; /* Determina la dimensione massima tra i vari segnali */ if (MPSigLen > InvFilterLen) SigLen = MPSigLen; else SigLen = InvFilterLen; if (EPSigLen > SigLen) SigLen = EPSigLen; /* Controlla se si deve adottare una potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca gli array per l'FFT */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < MPSigLen;I++) FFTArray1[I] = MPSig[I]; /* Azzera la parte rimanente */ for (I = MPSigLen;I < FS;I++) FFTArray1[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray1,FS); /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < EPSigLen;I++) FFTArray2[I] = EPSig[I]; /* Azzera la parte rimanente */ for (I = EPSigLen;I < FS;I++) FFTArray2[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Effettua l'inversione per l'estrazione degli effetti di pre-echo */ for (I = 0;I < FS;I++) FFTArray2[I] = std::polar((DLReal) 1.0,-std::arg(FFTArray2[I])); /* Riporta nel dominio del tempo */ IFft(FFTArray2,FS); /* Alloca l' array per l'estrazione della parte di pre-echo */ if ((AEPAbs = new DLReal[FS]) == NULL) return False; /* Estrae l'inverso della parte EP selezionando solo la zona di pre-echo */ for (I = 0; I < FS - EPSigLen;I++) AEPAbs[I] = 0; for (I = FS - EPSigLen; I < FS - (PEStart + EPSigLen / 2);I++) AEPAbs[I] = std::real(FFTArray2[I]); for (I = FS - (PEStart + EPSigLen / 2); I < FS;I++) AEPAbs[I] = 0; SpacedBlackmanWindow(&AEPAbs[FS - EPSigLen],(EPSigLen / 2) - PEStart,(EPSigLen / 2) - 2 * PETransition,WFull); /* Riporta la porzione di pre-echo nel dominio della frequenza */ for (I = 0;I < FS;I++) FFTArray2[I] = AEPAbs[I]; Fft(FFTArray2,FS); /* Estrae l'array valori assoluti porzione di pre-echo */ for (I = 0;I < FS;I++) AEPAbs[I] = std::abs(FFTArray2[I]); /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < EPSigLen;I++) FFTArray2[I] = EPSig[I]; /* Azzera la parte rimanente */ for (I = EPSigLen;I < FS;I++) FFTArray2[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Calcola il valore massimo della componente di pre-echo */ EMax = 0; for (I = 0;I < FS;I++) { if (AEPAbs[I] > EMax) EMax = AEPAbs[I]; } /* Riscala il fattore di effort */ if (EffortFactor >= 0) EffortFactor = -EffortFactor / ((DLReal) 1.0 + EffortFactor); else EffortFactor = EffortFactor / (EffortFactor - (DLReal) 1.0); /* Effettua la fast deconvolution selettiva della componente EP */ for (I = 0;I < FS;I++) { /* Normalizza il valore assoluto */ EPAbs = AEPAbs[I] / EMax; /* Applica il fattore di effort controllando eventuali singolarit */ if (EPAbs <= (DLReal) 0.0) EPAbs = (DLReal) 1.0; else if (EPAbs >= (DLReal) 1.0) EPAbs = (DLReal) 0.0; else { EPAbs = (DLReal) 1.0 - sqrt(EPAbs); EPAbs = (EPAbs * ((DLReal) 1.0 + EffortFactor)) / ((DLReal) 1.0 + EPAbs * EffortFactor); } /* Calcola la trasformata della deconvoluzione selettiva */ FFTArray2[I] = std::polar((DLReal) EPAbs,-std::arg(FFTArray2[I])) + std::polar(1.0 - EPAbs,(I * M_PI * EPSigLen) / FS); } /* Dealloca gli array temporanei */ delete[] AEPAbs; /* Compone l'inverso componente MP e EP */ for (I = 0;I < FS;I++) FFTArray1[I] = std::polar(1,std::arg(FFTArray2[I])) / FFTArray1[I]; /* Ritorna nel dominio del tempo */ IFft(FFTArray1,FS); /* Estrae il filtro inverso */ for (I = 0,J = (1 + FS + FS - (MPSigLen + EPSigLen + InvFilterLen) / 2) % FS;I < InvFilterLen;I++,J = (J + 1) % FS) InvFilter[I] = std::real(FFTArray1[J]); /* Dealloca gli array temporanei */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a troncatura degli effetti di pre echo */ Boolean PETFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, char PEType, int PELowerWindow, int PEUpperWindow, DLReal PEStartFreq, DLReal PEEndFreq, int PEFilterLen, DLReal FSharpness, int PEBandSplit, DLReal PEWindowExponent, const SLPPrefilteringType SLPType, const DLReal OGainFactor, int SampleRate, int MExp) { /* Dimensione da considerare per il segnale */ int SigLen; /* Dimensione FFT */ int FS; /* Array FFT */ DLComplex * FFTArray1; DLComplex * FFTArray2; /* Array rimozione pre-echo */ DLReal * EPIPERemove; /* Array prefiltratura componente EP */ DLReal * EPPFOut; /* Dimensione blocco di uscita filtratura */ int EPPFOutSize; /* Indici generici */ int I; int J; /* Determina la dimensione massima tra i vari segnali */ if (MPSigLen > InvFilterLen) SigLen = MPSigLen; else SigLen = InvFilterLen; if (EPSigLen > SigLen) SigLen = EPSigLen; /* Controlla se si deve adottare una potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca l'array per la componente EP */ if ((EPIPERemove = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo in ordine inverso in modo da ottenere direttamente il filtro inverso */ for (I = 0,J = FS - 1;I < EPSigLen;I++,J--) EPIPERemove[J] = EPSig[I]; /* Azzera la parte rimanente */ for (I = EPSigLen,J = 0;I < FS;I++,J++) EPIPERemove[J] = (DLReal) 0.0; /* Controlla il tipo di rimozione pre-echo da adottare */ if (PEType == 'f') { /* Estrae la parte EP rimuovendo la zona di pre-echo */ for (I = 0; I < FS - (PELowerWindow + EPSigLen / 2);I++) EPIPERemove[I] = 0; SpacedBlackmanWindow(&EPIPERemove[FS - (PELowerWindow + EPSigLen / 2)], PELowerWindow + EPSigLen / 2, (PELowerWindow + EPSigLen / 2) - 2 * (PELowerWindow - PEUpperWindow),WLeft); /* Verifica se si deve effettuare riappianamento */ if (OGainFactor >= 0) /* Rinormalizza a fase minima la componente EP inversa */ CMPNormFlat(EPIPERemove,FS,(DLReal) 1.0,OGainFactor,-1); } else { /* Calcola la dimesione effettiva del filtro */ if (PEFilterLen % 2 == 0) PEFilterLen--; /* Calcola la dimensione del blocco di uscita */ EPPFOutSize = 2 * PELowerWindow + PEFilterLen - 1; /* Alloca gli array per la finestratura */ if ((EPPFOut = new DLReal[EPPFOutSize]) == NULL) return False; /* Effettua la prefiltratura */ sputs("Inverted EP sliding lowpass pre-echo windowing..."); SLPreFilt(&EPIPERemove[FS - (PELowerWindow + EPSigLen / 2)], 2 * PELowerWindow,2 * PEUpperWindow,PEFilterLen, PEBandSplit,PEWindowExponent,SampleRate,PEStartFreq,PEEndFreq, 2 * PEUpperWindow,FSharpness,EPPFOut,WLeft,SLPType); /* Finestratura finale segnale prefiltrato */ SpacedBlackmanWindow(&EPPFOut[EPPFOutSize / 2 - PELowerWindow], 2 * PELowerWindow,2 * PEUpperWindow,WLeft); /* Ricompone la componente EP rimuovendo la zona di pre-echo */ for (I = 0; I < FS - (PELowerWindow + EPSigLen / 2);I++) EPIPERemove[I] = 0; for (I = FS - (PELowerWindow + EPSigLen / 2),J = EPPFOutSize / 2 - PELowerWindow;J < EPPFOutSize / 2;I++,J++) EPIPERemove[I] = EPPFOut[J]; /* Dealloca gli array prefiltratura */ delete[] EPPFOut; /* Segnala il resto della procedura */ sputs("Pre-echo truncation inversion completion..."); /* Verifica se si deve effettuare riappianamento */ if (OGainFactor >= 0) /* Rinormalizza a fase minima la componente EP inversa */ CMPNormFlat(EPIPERemove,FS,(DLReal) 1.0,OGainFactor,-1); } /* Alloca l'array per l'FFT componente EP */ if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Copia l'array componente EP in quello per l'FFT */ for (I = 0;I < FS;I++) FFTArray2[I] = EPIPERemove[I]; /* Dealloca l'array componente EP */ delete[] EPIPERemove; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Alloca l'array per l'FFT componente MP */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < MPSigLen;I++) FFTArray1[I] = MPSig[I]; /* Azzera la parte rimanente */ for (I = MPSigLen;I < FS;I++) FFTArray1[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray1,FS); /* Compone l'inverso componente MP e EP */ for (I = 0;I < FS;I++) FFTArray1[I] = FFTArray2[I] / FFTArray1[I]; /* Ritorna nel dominio del tempo */ IFft(FFTArray1,FS); /* Estrae il filtro inverso */ for (I = 0,J = (1 + FS + FS - (MPSigLen + EPSigLen + InvFilterLen) / 2) % FS;I < InvFilterLen;I++,J = (J + 1) % FS) InvFilter[I] = std::real(FFTArray1[J]); /* Dealloca gli array temporanei */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } /* Experimental, ignore it */ /* Inversione tramite selective minimum pahse fast deconvolution */ /* Versione a troncatura multipla degli effetti di pre echo con componente EP di riferimento */ Boolean MRefPETFDInvert(const DLReal * MPSig, int MPSigLen, const DLReal * EPSig, int EPSigLen, DLReal * InvFilter, int InvFilterLen, char PEType, int PELowerWindow, int PEUpperWindow, DLReal PEStartFreq, DLReal PEEndFreq, int PEFilterLen, DLReal FSharpness, int PEBandSplit, DLReal PEWindowExponent, const SLPPrefilteringType SLPType, const DLReal * EPRef, int EPRefLen, char RPEType, int RPELowerWindow, int RPEUpperWindow, DLReal RPEStartFreq, DLReal RPEEndFreq, int RPEFilterLen, DLReal RFSharpness, int RPEBandSplit, DLReal RPEWindowExponent, const SLPPrefilteringType RSLPType, const DLReal OGainFactor, int SampleRate, int MExp) { /* Dimensione da considerare per il segnale */ int SigLen; /* Dimensione FFT */ int FS; /* Array FFT */ DLComplex * FFTArray1; DLComplex * FFTArray2; /* Array rimozione pre-echo */ DLReal * EPIPERemove; /* Componente EP di riferimento */ DLComplex * EPFDRef; /* Array prefiltratura componente EP */ DLReal * EPPFOut; /* Dimensione blocco di uscita filtratura */ int EPPFOutSize; /* Indici generici */ int I; int J; /* Determina la dimensione massima tra i vari segnali */ if (MPSigLen > InvFilterLen) SigLen = MPSigLen; else SigLen = InvFilterLen; if (EPSigLen > SigLen) SigLen = EPSigLen; /* Controlla se si deve adottare una potenza di due */ if (MExp >= 0) { /* Calcola la potenza di due superiore a N */ for(FS = 1;FS <= SigLen;FS <<= 1); FS *= 1 << MExp; } else FS = SigLen; /* Alloca l'array per la componente EP */ if ((EPIPERemove = new DLReal[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo in ordine inverso in modo da ottenere direttamente il filtro inverso */ for (I = 0,J = FS - 1;I < EPSigLen;I++,J--) EPIPERemove[J] = EPSig[I]; /* Azzera la parte rimanente */ for (I = EPSigLen,J = 0;I < FS;I++,J++) EPIPERemove[J] = (DLReal) 0.0; /* Alloca l'array per l'FFT componente EP */ if ((FFTArray2 = new DLComplex[FS]) == NULL) return False; /* Verifica se la rimozione pre-echo con riferimento abilitata */ if (RPEType != 'n') { /* Alloca l'array per la convoluzione con il riferimento */ if ((EPFDRef = new DLComplex[FS]) == NULL) return False; /* Copia il riferimento allineandolo per ritardo zero */ for (I = 0,J = FS - EPRefLen / 2;I < EPRefLen / 2;I++,J++) EPFDRef[J] = EPRef[I]; for (I = EPRefLen / 2,J = 0;J < EPRefLen / 2;I++,J++) EPFDRef[J] = EPRef[I]; /* Azzera la parte rimanente */ for (I = EPRefLen / 2;I < FS - EPRefLen / 2;I++) EPFDRef[I] = 0; /* Porta nel dominio della frequenza */ Fft(EPFDRef,FS); /* Copia l'array componente EP in quello per l'FFT */ for (I = 0;I < FS;I++) FFTArray2[I] = EPIPERemove[I]; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Effettua la convoluzione tra il filtro inverso e il riferimento */ for (I = 0;I < FS;I++) /* FFTArray2[I] *= std::polar(((DLReal) 1.0), std::arg(EPFDRef[I])); */ FFTArray2[I] *= EPFDRef[I]; /* Riporta nel dominio del tempo */ IFft(FFTArray2,FS); /* Estrae la risposta nel tempo */ for (I = 0; I < FS;I++) EPIPERemove[I] = std::real(FFTArray2[I]); /* Controlla il tipo di rimozione pre echo da adottare */ if (RPEType == 'f') { /* Estrae la parte EP rimuovendo la zona di pre-echo */ for (I = 0; I < FS - (RPELowerWindow + EPSigLen / 2);I++) EPIPERemove[I] = 0; SpacedBlackmanWindow(&EPIPERemove[FS - (RPELowerWindow + EPSigLen / 2)], RPELowerWindow + EPSigLen / 2, (RPELowerWindow + EPSigLen / 2) - 2 * (RPELowerWindow - RPEUpperWindow),WLeft); } else { /* Calcola la dimesione effettiva del filtro */ if (RPEFilterLen % 2 == 0) RPEFilterLen--; /* Calcola la dimensione del blocco di uscita */ EPPFOutSize = 2 * RPELowerWindow + RPEFilterLen - 1; /* Alloca gli array per la finestratura */ if ((EPPFOut = new DLReal[EPPFOutSize]) == NULL) return False; /* Effettua la prefiltratura */ sputs("Inverted EP sliding lowpass pre-echo windowing..."); SLPreFilt(&EPIPERemove[FS - (RPELowerWindow + EPSigLen / 2)], 2 * RPELowerWindow,2 * RPEUpperWindow,RPEFilterLen, RPEBandSplit,RPEWindowExponent,SampleRate,RPEStartFreq,RPEEndFreq, 2 * RPEUpperWindow,RFSharpness,EPPFOut,WLeft,RSLPType); /* Finestratura finale segnale prefiltrato */ SpacedBlackmanWindow(&EPPFOut[EPPFOutSize / 2 - RPELowerWindow], 2 * RPELowerWindow,2 * RPEUpperWindow,WLeft); /* Estrae la parte EP rimuovendo la zona di pre-echo */ for (I = 0; I < FS - (RPELowerWindow + EPSigLen / 2);I++) EPIPERemove[I] = 0; for (I = FS - (RPELowerWindow + EPSigLen / 2),J = EPPFOutSize / 2 - RPELowerWindow;J < EPPFOutSize / 2;I++,J++) EPIPERemove[I] = EPPFOut[J]; /* Verifica se si deve effettuare riappianamento */ if (OGainFactor >= 0) /* Rinormalizza a fase minima la componente EP inversa */ CMPNormFlat(EPIPERemove,FS,(DLReal) 1.0,OGainFactor,-1); /* Dealloca gli array prefiltratura */ delete[] EPPFOut; } /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < FS;I++) FFTArray2[I] = EPIPERemove[I]; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Rimuove per deconvoluzione il riferimento */ for (I = 0;I < FS;I++) /*FFTArray2[I] /= EPFDRef[I];*/ FFTArray2[I] *= std::polar(((DLReal) 1.0), -std::arg(EPFDRef[I])); /* Dealloca gli array temporanei */ delete[] EPFDRef; /* Riporta nel dominio nel tempo */ IFft(FFTArray2,FS); /* Estrae la risposta nel tempo */ for (I = 0; I < FS;I++) EPIPERemove[I] = std::real(FFTArray2[I]); } /* Controlla il tipo di rimozione pre-echo da adottare */ if (PEType == 'f') { /* Estrae la parte EP rimuovendo la zona di pre-echo */ for (I = 0; I < FS - (PELowerWindow + EPSigLen / 2);I++) EPIPERemove[I] = 0; SpacedBlackmanWindow(&EPIPERemove[FS - (PELowerWindow + EPSigLen / 2)], PELowerWindow + EPSigLen / 2, (PELowerWindow + EPSigLen / 2) - 2 * (PELowerWindow - PEUpperWindow),WLeft); /* Verifica se si deve effettuare riappianamento */ if (OGainFactor >= 0) /* Rinormalizza a fase minima la componente EP inversa */ CMPNormFlat(EPIPERemove,FS,(DLReal) 1.0,OGainFactor,-1); } else { /* Calcola la dimesione effettiva del filtro */ if (PEFilterLen % 2 == 0) PEFilterLen--; /* Calcola la dimensione del blocco di uscita */ EPPFOutSize = 2 * PELowerWindow + PEFilterLen - 1; /* Alloca gli array per la finestratura */ if ((EPPFOut = new DLReal[EPPFOutSize]) == NULL) return False; /* Effettua la prefiltratura */ sputs("Inverted EP sliding lowpass pre-echo windowing..."); SLPreFilt(&EPIPERemove[FS - (PELowerWindow + EPSigLen / 2)], 2 * PELowerWindow,2 * PEUpperWindow,PEFilterLen, PEBandSplit,PEWindowExponent,SampleRate,PEStartFreq,PEEndFreq, 2 * PEUpperWindow,FSharpness,EPPFOut,WLeft,SLPType); /* Finestratura finale segnale prefiltrato */ SpacedBlackmanWindow(&EPPFOut[EPPFOutSize / 2 - PELowerWindow], 2 * PELowerWindow,2 * PEUpperWindow,WLeft); /* Ricompone la componente EP rimuovendo la zona di pre-echo */ for (I = 0; I < FS - (PELowerWindow + EPSigLen / 2);I++) EPIPERemove[I] = 0; for (I = FS - (PELowerWindow + EPSigLen / 2),J = EPPFOutSize / 2 - PELowerWindow;J < EPPFOutSize / 2;I++,J++) EPIPERemove[I] = EPPFOut[J]; /* Dealloca gli array prefiltratura */ delete[] EPPFOut; /* Segnala il resto della procedura */ sputs("Pre-echo truncation inversion completion..."); /* Verifica se si deve effettuare riappianamento */ if (OGainFactor >= 0) /* Rinormalizza a fase minima la componente EP inversa */ CMPNormFlat(EPIPERemove,FS,(DLReal) 1.0,OGainFactor,-1); } /* Copia l'array componente EP in quello per l'FFT */ for (I = 0;I < FS;I++) FFTArray2[I] = EPIPERemove[I]; /* Dealloca l'array componente EP */ delete[] EPIPERemove; /* Porta nel dominio della frequenza */ Fft(FFTArray2,FS); /* Alloca l'array per l'FFT componente MP */ if ((FFTArray1 = new DLComplex[FS]) == NULL) return False; /* Copia l'array sorgente in quello temporaneo */ for (I = 0;I < MPSigLen;I++) FFTArray1[I] = MPSig[I]; /* Azzera la parte rimanente */ for (I = MPSigLen;I < FS;I++) FFTArray1[I] = 0; /* Porta nel dominio della frequenza */ Fft(FFTArray1,FS); /* Compone l'inverso componente MP e EP */ for (I = 0;I < FS;I++) FFTArray1[I] = FFTArray2[I] / FFTArray1[I]; /* Ritorna nel dominio del tempo */ IFft(FFTArray1,FS); /* Estrae il filtro inverso */ for (I = 0,J = (1 + FS + FS - (MPSigLen + EPSigLen + InvFilterLen) / 2) % FS;I < InvFilterLen;I++,J = (J + 1) % FS) InvFilter[I] = std::real(FFTArray1[J]); /* Dealloca gli array temporanei */ delete[] FFTArray1; delete[] FFTArray2; /* Operazione completata */ return True; } drc-3.2.2/source/convol.cpp0000644000076400001450000001713313164712446014572 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : Convol.cpp Autore : Sbragion Denis Descrizione : Funzioni per la convoluzione. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #include "convol.h" #include "fft.h" /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif void Convolve(const DLReal * A,unsigned int NA,const DLReal * B, unsigned int NB,DLReal * R) { unsigned int I,J,S,E,NR = NA+NB-1; for(I = 0;I < NR;I++) { if (I < NB) S = 0; else S = I-NB+1; if (I < NA) E = I+1; else E = NA; R[I] = 0; for(J = S;J < E;J++) R[I] += A[J]*B[I-J]; } } void Convolve(const DLComplex * A,unsigned int NA,const DLComplex * B, unsigned int NB,DLComplex * R) { unsigned int I,J,S,E,NR = NA+NB-1; for(I = 0;I < NR;I++) { if (I < NB) S = 0; else S = I-NB+1; if (I < NA) E = I+1; else E = NA; R[I] = 0; for(J = S;J < E;J++) R[I] += A[J]*B[I-J]; } } Boolean DFftConvolve(const DLReal * A,unsigned int NA,const DLReal * B, unsigned int NB,DLReal * R,DLComplex * CA,DLComplex * CB) { unsigned int I; unsigned int L; unsigned int FS; DLComplex * FA; DLComplex * FB; L = NA + NB - 1; for(FS = 1;FS < L;FS <<= 1); if (CA != NULL) FA = CA; else if ((FA = new DLComplex[FS]) == NULL) return(False); if (CB != NULL) FB = CB; else if ((FB = new DLComplex[FS]) == NULL) { if (CA != NULL) delete[](FA); return(False); } for(I = 0;I < NA;I++) FA[I] = A[I]; for(I = NA;I < FS;I++) FA[I] = 0; Radix2Fft(FA,FS); for(I = 0;I < NB;I++) FB[I] = B[I]; for(I = NB;I < FS;I++) FB[I] = 0; Radix2Fft(FB,FS); for(I = 0;I < FS;I++) FA[I] *= FB[I]; Radix2IFft(FA,FS); for(I = 0;I < L;I++) R[I] = FA[I].real(); if (CA == NULL) delete[] FA; if (CB == NULL) delete[] FB; return(True); } Boolean DFftConvolve(const DLComplex * A,unsigned int NA,const DLComplex * B, unsigned int NB, DLComplex * R,DLComplex * CA,DLComplex * CB) { unsigned int I; unsigned int L; unsigned int FS; DLComplex * FA; DLComplex * FB; L = NA + NB - 1; for(FS = 1;FS < L;FS <<= 1); if (CA != NULL) FA = CA; else if ((FA = new DLComplex[FS]) == NULL) return(False); if (CB != NULL) FB = CB; else if ((FB = new DLComplex[FS]) == NULL) { if (CA != NULL) delete[](FA); return(False); } for(I = 0;I < NA;I++) FA[I] = A[I]; for(I = NA;I < FS;I++) FA[I] = 0; Radix2Fft(FA,FS); for(I = 0;I < NB;I++) FB[I] = B[I]; for(I = NB;I < FS;I++) FB[I] = 0; Radix2Fft(FB,FS); for(I = 0;I < FS;I++) FA[I] *= FB[I]; Radix2IFft(FA,FS); L = NA + NB - 1; for(I = 0;I < L;I++) R[I] = FA[I]; if (CA == NULL) delete[] FA; if (CB == NULL) delete[] FB; return(True); } Boolean OAFftConvolve(const DLReal * A,unsigned int NA,const DLReal * B, unsigned int NB,DLReal * R,DLComplex * CA,DLComplex * CB) { unsigned int I,J,INA,INB,FS,L,NR = NA+NB-1; const DLReal * IA; const DLReal * IB; DLComplex * FA; DLComplex * FB; Boolean FAAlloc; Boolean FBAlloc; if (NA <= NB) { INA = NA; INB = NB; IA = A; IB = B; } else { INA = NB; INB = NA; IA = B; IB = A; } for(FS = 1;FS <= INA;FS <<= 1) { } FS *= 2; if (CA == NULL) { if ((FA = new DLComplex[FS]) == NULL) return(False); FAAlloc = True; } else { FA = CA; FAAlloc = False; } if (CB == NULL) { if ((FB = new DLComplex[FS]) == NULL) { if (FAAlloc == True) delete[](FA); return(False); } FBAlloc = True; } else { FB = CB; FBAlloc = False; } L = FS-INA+1; for(I = 0;I < INA;I++) FA[I] = IA[I]; for(I = INA;I < FS;I++) FA[I] = 0; Radix2Fft(FA,FS); for(I = 0;I < NR;I++) R[I] = 0; for(I = 0;I < NR;I += L) { for(J = 0;(J < L) && (I+J < INB);J++) FB[J] = IB[I+J]; for(;J < FS;J++) FB[J] = 0; Radix2Fft(FB,FS); for(J = 0;J < FS;J++) FB[J] *= FA[J]; Radix2IFft(FB,FS); for(J = 0;(J < FS) && (I+J < NR);J++) R[I+J] += FB[J].real(); } if (FAAlloc == True) delete[] FA; if (FBAlloc == True) delete[] FB; return(True); } Boolean OAFftConvolve(const DLComplex * A,unsigned int NA,const DLComplex * B, unsigned int NB, DLComplex * R,DLComplex * CA,DLComplex * CB) { unsigned int I,J,INA,INB,FS,L,NR = NA+NB-1; const DLComplex * IA; const DLComplex * IB; DLComplex * FA; DLComplex * FB; Boolean FAAlloc; Boolean FBAlloc; if (NA <= NB) { INA = NA; INB = NB; IA = A; IB = B; } else { INA = NB; INB = NA; IA = B; IB = A; } for(FS = 1;FS <= INA;FS <<= 1) { } FS *= 2; if (CA == NULL) { if ((FA = new DLComplex[FS]) == NULL) return(False); FAAlloc = True; } else { FA = CA; FAAlloc = False; } if (CB == NULL) { if ((FB = new DLComplex[FS]) == NULL) { if (FAAlloc == True) delete[](FA); return(False); } FBAlloc = True; } else { FB = CB; FBAlloc = False; } L = FS-INA+1; for(I = 0;I < INA;I++) FA[I] = IA[I]; for(I = INA;I < FS;I++) FA[I] = 0; Radix2Fft(FA,FS); for(I = 0;I < NR;I++) R[I] = 0; for(I = 0;I < NR;I += L) { for(J = 0;(J < L) && (I+J < INB);J++) FB[J] = IB[I+J]; for(;J < FS;J++) FB[J] = 0; Radix2Fft(FB,FS); for(J = 0;J < FS;J++) FB[J] *= FA[J]; Radix2IFft(FB,FS); for(J = 0;(J < FS) && (I+J < NR);J++) R[I+J] += FB[J]; } if (FAAlloc == True) delete[] FA; if (FBAlloc == True) delete[] FB; return(True); } /***************************************************************************/ drc-3.2.2/source/glsweep.depend0000644000076400001450000000004013165107124015372 0ustar denisitadm# depslib dependency file v1.0 drc-3.2.2/source/toeplitz.cpp0000644000076400001450000000500313164712707015135 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /* Risoluzione matrici Toeplitz */ #include "toeplitz.h" /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif int ToeplitzSolve(const DLReal * A, const DLReal * B, DLReal * X, int N) { int I, J, K; DLReal PError; DLReal RC; DLReal Tmp; DLReal Sum; DLReal * TA; PError = A[0]; if (PError <= 0) return 1; /* Alloca un arrya temporaneo */ if ((TA = new DLReal[N]) == NULL) return 1; X[0] = B[0] / PError; for (K = 0; K < N - 1; K++) { Sum = A[K + 1]; for (I = 0; I < K; I++) Sum = Sum - A[K - I] * TA[I]; RC = -Sum / PError; /* Calcola l'errore del predittore (equivalente a PError = PError * (1 - RC**2). Un cambio di segno di PError indica che RC maggiore dell'unit e quindi siamo di fronte ad un sistema di equazioni che non definito positivo */ PError = PError + RC * Sum; if (PError <= 0.0) { delete[] TA; return 1; } TA[K] = -RC; for (I = 0, J = K - 1; I < J; I++, J--) { Tmp = TA[I] + RC * TA[J]; TA[J] = TA[J] + RC * TA[I]; TA[I] = Tmp; } if (I == J) TA[I] = TA[I] + RC * TA[I]; Sum = B[K+1]; for (I = 0, J = K + 1; I <= K; I++, J--) Sum = Sum - X[I] * A[J]; X[K + 1] = Sum / PError; for (I = 0, J = K; I <= K; I++, J--) X[I] = X[I] - X[K + 1] * TA[J]; } /* Rimuove l'array temporaneo */ delete[] TA; return 0; } drc-3.2.2/source/boolean.h0000644000076400001450000000310013162156312014333 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : None. File : Boolean.h Autore : Sbragion Denis Descrizione : Definizione tipo booleano standard. Revisioni : 26/1/94 : Prima stesura. ****************************************************************************/ #ifndef Boolean_h #define Boolean_h /* Tipo booleano standard. */ /* False = 0, True = 1. */ typedef enum { False, True } Boolean; #endif /***************************************************************************/ drc-3.2.2/source/lcase0000644000076400001450000000025710350310446013563 0ustar denisitadm#!/bin/sh for file in * do lcfile=$( eval echo -n $file | tr '[:upper:]' '[:lower:]') echo "$file -> $lcfile" if [ "$file" != $lcfile ] then mv $file $lcfile fi done drc-3.2.2/source/getopt/0000755000076400001450000000000013165107357014063 5ustar denisitadmdrc-3.2.2/source/getopt/getopt.h0000644000076400001450000001114610156024644015533 0ustar denisitadm/* Declarations for getopt. Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt(int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt(); #endif /* __GNU_LIBRARY__ */ extern int getopt_long(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal(int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt(); extern int getopt_long(); extern int getopt_long_only(); extern int _getopt_internal(); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ drc-3.2.2/source/getopt/getopt1.c0000644000076400001450000001104510156024646015607 0ustar denisitadm/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "getopt.h" #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #endif #ifndef NULL #define NULL 0 #endif int getopt_long(argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal(argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only(argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal(argc, argv, options, long_options, opt_index, 1); } #endif /* Not ELIDE_CODE. */ #ifdef TEST #include int main(argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf("option %c\n", c); break; case 'a': printf("option a\n"); break; case 'b': printf("option b\n"); break; case 'c': printf("option c with value `%s'\n", optarg); break; case 'd': printf("option d with value `%s'\n", optarg); break; case '?': break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); } exit(0); } #endif /* TEST */ drc-3.2.2/source/getopt/readme.txt0000644000076400001450000000060610642376166016066 0ustar denisitadmThis directory includes a portable version of the GNU getopt and getopt_long functions for systems which are missing these functions. The compilation of the files included here should be automatically excluded on systems already providing the getopt and getopt_long functions. If you get compilation conflicts remove these files from the list of compiled files.drc-3.2.2/source/getopt/getopt.c0000644000076400001450000007000313164711075015526 0ustar denisitadm/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_STRINGS_H #include #endif #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #define GETOPT_INTERFACE_VERSION 2 #if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 #include #if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION #define ELIDE_CODE #endif #endif #ifndef ELIDE_CODE /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #include #endif /* GNU C library. */ #ifdef VMS #include #if HAVE_STRING_H - 0 #include #ifdef STRNCASECMP_IN_STRINGS_H # include #endif #endif #endif #if defined (WIN32) && !defined (__CYGWIN32__) /* It's not Unix, really. See? Capital letters. */ #include #define getpid() GetCurrentProcessId() #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ #ifdef HAVE_LIBINTL_H #include #define _(msgid) gettext (msgid) #else #define _(msgid) (msgid) #endif #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ int optind = 1; /* Formerly, initialization of getopt depended on optind==0, which causes problems with re-calling getopt as programs generally don't know that. */ int __getopt_initialized = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ char *getenv(); static char * my_index(str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ #if !defined (__STDC__) || !__STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen(const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #ifdef _LIBC /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ static const char *nonoption_flags; static int nonoption_flags_len; static int original_argc; static char *const *original_argv; /* Make sure the environment variable bash 2.0 puts in the environment is valid for the getopt call we must make sure that the ARGV passed to getopt is that one passed to the process. */ static void store_args(int argc, char *const *argv) __attribute__((unused)); static void store_args(int argc, char *const *argv) { /* XXX This is no good solution. We should rather copy the args so that we can compare them later. But we must not use malloc(3). */ original_argc = argc; original_argv = argv; } text_set_element(__libc_subinit, store_args); #endif /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined (__STDC__) && __STDC__ static void exchange(char **); #endif static void exchange(argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ #if defined (__STDC__) && __STDC__ static const char *_getopt_initialize(int, char *const *, const char *); #endif static const char * _getopt_initialize(argc, argv, optstring) int argc; char *const *argv; const char *optstring; { /* Get rid of unused argument warnings */ (void) argc; (void) argv; /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind = 1; nextchar = NULL; posixly_correct = getenv("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; #ifdef _LIBC if (posixly_correct == NULL && argc == original_argc && argv == original_argv) { /* Bash 2.0 puts a special variable in the environment for each command it runs, specifying which ARGV elements are the results of file name wildcard expansion and therefore should not be considered as options. */ char var[100]; sprintf(var, "_%d_GNU_nonoption_argv_flags_", getpid()); nonoption_flags = getenv(var); if (nonoption_flags == NULL) nonoption_flags_len = 0; else nonoption_flags_len = strlen(nonoption_flags); } else nonoption_flags_len = 0; #endif return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal(argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (!__getopt_initialized || optind == 0) { optstring = _getopt_initialize(argc, argv, optstring); optind = 1; /* Don't scan ARGV[0], the program name. */ __getopt_initialized = 1; } /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag from the shell indicating it is not an option. The later information is only used when the used in the GNU libc. */ #ifdef _LIBC #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && nonoption_flags[optind] == '1')) #else #define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been moved back by the user (who may also have changed the arguments). */ if (last_nonopt > optind) last_nonopt = optind; if (first_nonopt > optind) first_nonopt = optind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && NONOPTION_P) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp(argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index(optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp(p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen(p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf(stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen(nextchar); optind++; optopt = 0; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf(stderr, _("%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ fprintf(stderr, _("%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen(nextchar); optopt = pfound->val; return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf(stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen(nextchar); optopt = pfound->val; return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen(nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index(optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf(stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ fprintf(stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; optopt = 0; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index(optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf(stderr, _("%s: illegal option -- %c\n"), argv[0], c); else fprintf(stderr, _("%s: invalid option -- %c\n"), argv[0], c); } optopt = c; return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf(stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; /* optarg is now the argument, see if it's in the table of longopts. */ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp(p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen(p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf(stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[optind]); nextchar += strlen(nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) fprintf(stderr, _("\ %s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); nextchar += strlen(nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf(stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]); nextchar += strlen(nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen(nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf(stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt(argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal(argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main(argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt(argc, argv, "abc:d:0123456789"); if (c == -1) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf("option %c\n", c); break; case 'a': printf("option a\n"); break; case 'b': printf("option b\n"); break; case 'c': printf("option c with value `%s'\n", optarg); break; case '?': break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf("non-option ARGV-elements: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); } exit(0); } #endif /* TEST */ drc-3.2.2/source/fft.cpp0000644000076400001450000003552713165103160014044 0ustar denisitadm/**************************************************************************** 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@neomerica.it ****************************************************************************/ /**************************************************************************** Progetto : DSP Library. File : Fft.cpp Autore : Sbragion Denis Descrizione : Funzioni per fft, ifft etc. Revisioni : 16/10/93 : Prima stesura. ****************************************************************************/ #include "fft.h" #include /* Memory leaks debugger */ #ifdef DebugMLeaks #include "debug_new.h" #endif DLComplex Power(DLComplex X,unsigned int N) { unsigned int I; DLComplex Pow(1); for(I = 1;I <= N;I <<= 1) { if ((I & N) != 0) Pow *= X; X *= X; } return(Pow); } DLComplex UnitRoot(unsigned int I,unsigned int N) { DLReal Arg = (DLReal) (((2*M_PI)*(I%N))/N); return(DLComplex((DLReal) DLCos(Arg),(DLReal) DLSin(Arg))); } unsigned int FirstFactor(unsigned int N) { unsigned int I; if (N < 2) return(1); else if (N%2 == 0) return(2); else { for(I = 3;I <= N/I && N%I != 0; I += 2); if (I > N/I) I = N; } return(I); } /* Controlla se ablitato l'uso della FFT GSL o di Ooura */ #if !defined(UseGSLFft) && !defined(UseOouraFft) static unsigned int Radix2Reverse(unsigned int I,unsigned int N) { unsigned int IR,J,Bit; IR = 0; for(J = 1,Bit = N >> 1;J < N;J <<= 1,Bit >>= 1) if((I & J) != 0) IR |= Bit; return(IR); } static void Radix2Shuffle(DLComplex P[],unsigned int N) { unsigned int I,IR; DLComplex Temp; for(I = 0;I < N;I++) { IR = Radix2Reverse(I,N); if(I < IR) { Temp = P[I]; P[I] = P[IR]; P[IR] = Temp; } } } static void DLRadix2Fft(DLComplex P[],unsigned int N) { unsigned int I,J,K,Span,Start,End; DLComplex P0,Root; for(K = 0,Span = N >> 1;K < Span;K++) { P0 = P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } for(I = 2,Span >>= 1;I < N;I <<= 1,Span >>= 1) { for(J = 0;J < I;J++) { Root = std::conj(UnitRoot(J,I << 1)); Start = (Radix2Reverse(J,I) << 1)*Span; End = Start+Span; for(K = Start;K < End;K++) { P0 = Root*P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } } } Radix2Shuffle(P,N); } static void DLRadix2IFft(DLComplex P[],unsigned int N) { unsigned int I,J,K,Span,Start,End; DLComplex P0,Root; for(K = 0,Span = N >> 1;K < Span;K++) { P0 = P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } for(I = 2,Span >>= 1;I < N;I <<= 1,Span >>= 1) { for(J = 0;J < I;J++) { Root = UnitRoot(J,I << 1); Start = (Radix2Reverse(J,I) << 1)*Span; End = Start+Span; for(K = Start;K < End;K++) { P0 = Root*P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } } } Radix2Shuffle(P,N); for(I = 0;I < N;I++) P[I] /= (DLReal) N; } #endif /* Verifica se abiliato l'uso della GSL */ #ifndef UseGSLFft static unsigned int MixedReverse(unsigned int I,unsigned int N) { unsigned int IR,J,Digit,Radix; if (N < 2) return(I); else { IR = 0; Radix = FirstFactor(N); for(J = 1,Digit = N/Radix;J < N;Digit /= Radix) { IR += ((I/J)%Radix)*Digit; J *= Radix; Radix = FirstFactor(Digit); } } return(IR); } static void MixedShuffle(DLComplex P[],unsigned int N) { unsigned int I,IR,J; DLComplex Temp; for(I = 1;I < N-1;I++) { IR = MixedReverse(I,N); while(I > IR) IR = MixedReverse(IR,N); if (I == IR) { J = I; IR = MixedReverse(I,N); Temp = P[J]; while(I != IR) { P[J] = P[IR]; J = IR; IR = MixedReverse(IR,N); } P[J] = Temp; } } } static Boolean DLFft(DLComplex P[],unsigned int N) { unsigned int I,J,K,L,Span,Radix,Start,End,RP; DLComplex * PT; DLComplex Root,P0; Radix = FirstFactor(N); for(I = 1,Span = N/Radix;I < N;Span /= Radix) { RP = I*Radix; if (Radix == 2) if (I == 1) for(K = 0;K < Span;K++) { P0 = P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } else for(J = 0;J < I;J++) { Start = MixedReverse(J,I)*Radix*Span; End = Start+Span; Root = std::conj(UnitRoot(J,RP)); for(K = Start;K < End;K++) { P0 = Root*P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } } else if ((PT = new(DLComplex[Radix])) != NULL) { for(J = 0;J < I;J++) { Start = MixedReverse(J,I)*Radix*Span; End = Start+Span; for(K = Start;K < End;K++) { for (L = 0;L < Radix;L++) PT[L] = P[Span*L+K]; for (L = 0;L < Radix;L++) P[Span*L+K] = PolyEval(PT,Radix,std::conj(UnitRoot(L*I+J,RP))); } } delete[](PT); } else return(False); I *= Radix; Radix = FirstFactor(Span); } MixedShuffle(P,N); return(True); } static Boolean DLIFft(DLComplex P[],unsigned int N) { unsigned int I,J,K,L,Span,Radix,Start,End,RP; DLComplex * PT; DLComplex Root,P0; Radix = FirstFactor(N); for(I = 1,Span = N/Radix;I < N;Span /= Radix) { RP = I*Radix; if (Radix == 2) if (I == 1) for(K = 0;K < Span;K++) { P0 = P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } else for(J = 0;J < I;J++) { Start = MixedReverse(J,I)*Radix*Span; End = Start+Span; Root = UnitRoot(J,RP); for(K = Start;K < End;K++) { P0 = Root*P[Span+K]; P[Span+K] = P[K]-P0; P[K] += P0; } } else if ((PT = new(DLComplex[Radix])) != NULL) { for(J = 0;J < I;J++) { Start = MixedReverse(J,I)*Radix*Span; End = Start+Span; for(K = Start;K < End;K++) { for (L = 0;L < Radix;L++) PT[L] = P[Span*L+K]; for (L = 0;L < Radix;L++) P[Span*L+K] = PolyEval(PT,Radix, UnitRoot(L*I+J,RP)); } } delete[](PT); } else return(False); I *= Radix; Radix = FirstFactor(Span); } MixedShuffle(P,N); for(I = 0;I < N;I++) P[I] /= (DLReal) N; return(True); } #else #include #endif /* Controlla se ablitato l'uso della FFT di Ooura */ #ifdef UseOouraFft #include "fftsg.h" #include static unsigned int OTSize = 0; static int * OWATable = NULL; static DRCFloat * OCSTable = NULL; static void FreeWAAndCS(void) { if (OWATable != NULL) { free(OWATable); OWATable = NULL; } if (OCSTable != NULL) { free(OCSTable); OCSTable = NULL; OTSize = 0; } } static Boolean CheckWAAndCS(unsigned int N) { if (OWATable == NULL) { atexit(FreeWAAndCS); OWATable = (int *) malloc(sizeof(int) * (int) ceil(2 + sqrt(N))); if (OWATable == NULL) return(False); OWATable[0] = 0; OCSTable = (DRCFloat *) malloc(sizeof(DRCFloat) * N / 2); if (OCSTable == NULL) { FreeWAAndCS(); return(False); } } else if (N / 2 > OTSize) { FreeWAAndCS(); OWATable = (int *) malloc(sizeof(int) * (int) ceil(2 + sqrt(N))); if (OWATable == NULL) return(False); OWATable[0] = 0; OCSTable = (DRCFloat *) malloc(sizeof(DRCFloat) * N / 2); if (OCSTable == NULL) { FreeWAAndCS(); return(False); } } return(True); } #endif /* Controlla se ablitato l'uso della FFT GSL */ #ifdef UseGSLFft #ifdef UseDouble #include "gsl/gsl_fft_complex.h" #define FftWTAlloc gsl_fft_complex_wavetable_alloc #define FftWTFree gsl_fft_complex_wavetable_free #define FftWSAlloc gsl_fft_complex_workspace_alloc #define FftWSFree gsl_fft_complex_workspace_free #define FftForward gsl_fft_complex_forward #define FftInverse gsl_fft_complex_inverse #define FftArrayType gsl_complex_packed_array #define FftWTType gsl_fft_complex_wavetable #define FftWSType gsl_fft_complex_workspace #else #include "gsl/gsl_fft_complex_float.h" #define FftWTAlloc gsl_fft_complex_wavetable_float_alloc #define FftWTFree gsl_fft_complex_wavetable_float_free #define FftWSAlloc gsl_fft_complex_workspace_float_alloc #define FftWSFree gsl_fft_complex_workspace_float_free #define FftForward gsl_fft_complex_float_forward #define FftInverse gsl_fft_complex_float_inverse #define FftArrayType gsl_complex_packed_array_float #define FftWTType gsl_fft_complex_wavetable_float #define FftWSType gsl_fft_complex_workspace_float #endif static FftWTType * FftWT = NULL; static FftWSType * FftWS = NULL; static void FreeWTAndWS(void) { if (FftWT != NULL) { FftWTFree(FftWT); FftWT = NULL; } if (FftWS != NULL) { FftWSFree(FftWS); FftWS = NULL; } } static Boolean CheckWTAndWS(unsigned int N) { if (FftWT == NULL) { atexit(FreeWTAndWS); FftWT = FftWTAlloc(N); if (FftWT == NULL) return(False); FftWS = FftWSAlloc(N); if (FftWS == NULL) { FreeWTAndWS(); return(False); } } else if (FftWT->n != N) { FreeWTAndWS(); FftWT = FftWTAlloc(N); if (FftWT == NULL) return(False); FftWS = FftWSAlloc(N); if (FftWS == NULL) { FreeWTAndWS(); return(False); } } return(True); } #endif void Radix2Fft(DLComplex P[],unsigned int N) { #ifdef UseOouraFft if (CheckWAAndCS(N) == False) return; cdft(2 * N,OouraForward,(DRCFloat *) P,OWATable,OCSTable); #else #ifdef UseGSLFft if (CheckWTAndWS(N) == False) return; FftForward((FftArrayType) P,1,N,FftWT,FftWS); #else DLRadix2Fft(P,N); #endif #endif } void Radix2IFft(DLComplex P[],unsigned int N) { #ifdef UseOouraFft unsigned int I; if (CheckWAAndCS(N) == False) return; cdft(2 * N,OouraBackward,(DRCFloat *) P,OWATable,OCSTable); for (I = 0;I < N;I++) P[I] /= (DRCFloat) N; #else #ifdef UseGSLFft if (CheckWTAndWS(N) == False) return; FftInverse((FftArrayType) P,1,N,FftWT,FftWS); #else DLRadix2IFft(P,N); #endif #endif } Boolean Fft(DLComplex P[],unsigned int N) { /* Controlla se la lunghezza una potenza di 2 */ if ((N & (N - 1)) > 0) { #ifdef UseGSLFft if (CheckWTAndWS(N) == False) return(False); if (FftForward((FftArrayType) P,1,N,FftWT,FftWS) != 0) return(False); #else return(DLFft(P,N)); #endif } else { #ifdef UseOouraFft if (CheckWAAndCS(N) == False) return(False); cdft(2 * N,OouraForward,(DRCFloat *) P,OWATable,OCSTable); #else #ifdef UseGSLFft if (CheckWTAndWS(N) == False) return(False); if (FftForward((FftArrayType) P,1,N,FftWT,FftWS) != 0) return(False); #else DLRadix2Fft(P,N); #endif #endif } return(True); } Boolean IFft(DLComplex P[],unsigned int N) { /* Controlla se la lunghezza una potenza di 2 */ if ((N & (N - 1)) > 0) { #ifdef UseGSLFft if (CheckWTAndWS(N) == False) return(False); if (FftInverse((FftArrayType) P,1,N,FftWT,FftWS) != 0) return(False); #else return(DLIFft(P,N)); #endif } else { #ifdef UseOouraFft unsigned int I; if (CheckWAAndCS(N) == False) return(False); cdft(2 * N,OouraBackward,(DRCFloat *) P,OWATable,OCSTable); for (I = 0;I < N;I++) P[I] /= (DRCFloat) N; #else #ifdef UseGSLFft if (CheckWTAndWS(N) == False) return(False); if (FftInverse((FftArrayType) P,1,N,FftWT,FftWS) != 0) return(False); #else DLRadix2IFft(P,N); #endif #endif } return(True); } DLComplex PolyEval(DLComplex P[],unsigned int N,DLComplex X) { DLComplex Y(0); unsigned int I; if (N > 0) { Y = P[N-1]; for(I = N-1;I > 0;I--) Y = X*Y+P[I-1]; } return(Y); } Boolean Dft(DLComplex P[],unsigned int N) { unsigned int I; DLComplex * R; if ((R = new DLComplex[N]) != NULL) { for(I = 0;I < N;I++) R[I] = PolyEval(P,N,std::conj(UnitRoot(I,N))); for(I = 0;I < N;I++) P[I] = R[I]; delete[](R); return(True); } else return(False); } Boolean IDft(DLComplex P[],unsigned int N) { unsigned int I; DLComplex * R; if ((R = new DLComplex[N]) != NULL) { for(I = 0;I < N;I++) R[I] = PolyEval(P,N,UnitRoot(I,N)); for(I = 0;I < N;I++) P[I] = R[I]/((DLReal) N); delete[](R); return(True); } else return(False); } /***************************************************************************/ drc-3.2.2/sample/0000755000076400001450000000000013165107236012536 5ustar denisitadmdrc-3.2.2/sample/erb-44.1.drc0000644000076400001450000001115311751752333014370 0ustar denisitadm# ERB scale approximation correction settings # The approximation is pretty accurate # The approximation has been computed considering: # df * dt = 2 # i.e. four time the Gabor limit. This is an estimation # of the real resolution achieved by the frequency # dependent windowing applied. # ERB appoximation windowind (65 ms at 20 Hz, 48.5 ms at 100 Hz, 12.6 ms at 1 kHz, 0.46 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # ERB approximation ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 40 MPLowerWindow = 5734 # 65 ms MPUpperWindow = 40 # 0.46 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.87 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 5734 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 40 EPLowerWindow = 1836 # 21.3 ms EPUpperWindow = 40 # 0.46 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1836 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 918 ISPEUpperWindow = 688 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 40 RTLowerWindow = 5734 # 65 ms RTUpperWindow = 40 # 0.46 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.87 RTOutWindow = 5734 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 918 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/sample/strong-44.1.drc0000644000076400001450000001053511751752333015137 0ustar denisitadm# Strong correction settings # Wide prefiltering windows (544 ms at 20 Hz, 108 ms at 100 Hz, 10.8 ms at 1 kHz, 0.54 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Soft pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Soft ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 48 MPLowerWindow = 48000 # 544 ms MPUpperWindow = 48 # 0.54 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 48000 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 48 EPLowerWindow = 2000 # 22.7 ms EPUpperWindow = 48 # 0.54 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2000 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1000 ISPEUpperWindow = 750 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 48 RTLowerWindow = 48000 # 544 ms RTUpperWindow = 48 # 0.54 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 48000 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1000 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/sample/rs.pcm0000644000076400001450000277777410311005516013706 0ustar denisitadm?48543z44rE64W2 4s2U4N4k4c3D4V 4:=[S3H5 4>54uZ\5YB4+4 4\X4UJw{44b3=ɏ3a[4451[l]!Y4Q$23~3F4_a4/C2ro34F~3Z4d45|4(5_34^{6 5ь4 4T05:3.4v4vO4eL4pM40)4444u4$46 5k4p45TP45J)53س5434Z"464hz4L4J&5Dx4=5qϲX4*R3R3PP 5*4Z 2w}3!4{342?#47Z4EHqȴl3JX{b3I3-3AB`4Jl W̴. iAտ$|3E3s(Z3g-W4]H/i#uSx[Gw2{#4Y*M4a*3fDвݖ!2VX3D4L³4703C3g@b4 444ǩ4-62zX{4R7373 234"M4OЅ4i<344H4S3:44h 3Mhb3 i 54)34^4s3&44)4-44:4龳#4=m4dB3SP3wg3jv4w#z33؉4$Q8mvU k}+ 4YXyN_r3DGJr[P4x˘վ@4 L354Ӫ(hF>xr2ql w@ʹ +HRBP4h%W+]6C4M9VW.d-cH O7_DI=J2q)(3_?]0!ln%wݴN  7&0 e]ഓѯ>28gx >A W$ϷU`*Bp,3tNѳտ3 k21#/%s@ 3CӺːRڴ:dӴj,~rě4\":ܴZŞlD'o5q״ TK側Kմ7ţR^!.1׸ZGS~  PѴP @6qɲo`W۳| ITд;l[D`дs\*!Ǵ3 5[1*4'L>fYBi+ l<ϴ)7`3"?_@ 43])[/Fa3>ۜ3&`3:{4Е0Z4P94\!3_%'xM4oϴe&TS3tƴxʹA K?ݲ_ֱ 4ͦ~P3xO۴-ִ?J> e. X&3&3lÞXJ&RǴ0dM;q% 2?IǴSGz3$Ae@"ٴDٴ2̴A 4\g_) +&mȗQvY6ഢ@/0nkCʹ&`b?Pؒ !`L*4BYXnz#[Y3ס"4J3J4u3س2+t/+4b5 7H Fѽñw'`3xv;4d3-4pb 3ԕ!4f ʳv@[34К,K-3&3=1F%!4 `{3k36s3N$4sBmO4%4S5BT3/<444I4g3"s434Z3l3z4k?4דN4a=4<3! 455-t444μ4$441f4m4 5^4C"4 H4$44N4FM4c34i`t:a3ƍ4A>Uh3a 5E@4"3<4~4ί1Na4@3ˤ*&45НZ41M4~4K3_3!)3a 444}Z4hpp5434%n4v[ʹ3+F431q4444ڳeO4~5 4X"44e4~O4Z[3-445b4Ws4>354۷4t4v\4Cs4B#H4.4l3B4_B1lư7h4 4b424 4fX4P}4î455k4q4 5xA5a854Y45@5ƅ55x52G 5 50j45&-5@4N 51z4,5MA4585[5[4 F)5p 5C5Z 5-$-5d5z35@]5hh5D5V5;5BF5i5 15y5]95x5|~556K5V5T5t<5as5{4O5$$5fm5J4UE5/a54T5=f5H5 35lD5٦45*55XR45o75/5TK5e)5t255aQE5r5Tf5)5>5n4w5F5ׁ5$ 5G<%>5g5c4][44C)5B05^5= 4?\4R44v25ȁ4.*44,d4_4m4Z%53v4DЀ4'4,4S4w4D!55 t4 !V4d0 45ޱ4p4y42v"457524Z'554"5]5`4,&5ab15ݖ44{15]4e4IG4ʰ35<*5-\5J:5nQ"5%5<467555;(5/Z55j44b.5[5 #4t44448]4˚5>95L5?5}4 44ZK5V/5]544oYw45&5 5O4 .:5| 5\55,Y5/5r4FZ4=554%4yM]4ƽ 4zU4i4̖46224@k4܅ً 5X4L2444#5.5fr*5h5KO4m|4vt4 55l4 *5W5l4ф544L4 c4_4443|4O 4 F4-5 44sD<4g5a4,44I 5f4"Mc55*s4C5R45]E55_5* 5%5ft-5~3 555 5x_5k<5*5]1654u4м{444a4J!5(5H4-b4 !5`4C4}43446!54c4>44݂484H5z45Z4i*5F5ġA4퍄4y44,4vߣ44ӹ44Pѵ4ij4/55YD4=4Z5ֈ4`4"!5I34W44C3n2S43QBt2 4ɞ3hUTX"34V|3d&2͖up״Y}R?5ٴ<3:DP%ʑq~en۴~ԅ$y!jQU]|}u-oJ⑲Gas$P}{2aQ]37ȴC40p tW~N3ד3g4e!3lq4~V42bno4!453"kC%nJVx3⏴pDz `t[Q4.7!0ԴԴ3i4>I\2ʕZ`,\m|o@d?޴!!@t(* մ_` Ӵn5=U杴;M'ttԹx+dմx̴ W)lϴC笴K`&VZV_ԴK3mzAg_]!40*Y}e8'7䡴ʳ/沥-^jdz[Oq!޳&*3svԆ14mhH4Y3~sBcF 8AySoDa~k*K<״@> ݙCҴa%p4(sJⳒմ"޴b[.fڴW# FUд`vϴu Ag*K@(1Q:6B^Br&}JTU]=/D(^fQ@kk*SnzA|b'2Ty$VG4.G_Sx[PU)UH `\(Dʹ˴%+(L״{ ҳ딭#m1kqL 4-L04-q32Aԧ12I4D 3Z4#43l1DwJ!+ٳ^ >4E4)J337m3]Z4ܕ4JB44T44hW4z4e4; 4"4G'4Q3]5Qrc4s4y434d14KW+3@-%s uO13S] 4Zf2#y.4`4 3qp3u.ANȀqP|5Q3| 4~8D32d@38ڳ*43_sK4.P41:@3ب3\7k#U4o 3L3;n\4zA4p14e32 Eb,35Z'33Q74>4 4 "4(t4գ4e4D4au}4 394O4-04L44 4ov40E5q4:4LM454G*3G-5}t4T445EN444X5u4454e4K_3333g3͸4;UD494>44 '34l\3ᕬp74u어A2CI(&L aa 4Ͼ14 h3)3(ŴcIt3/5. 44'4 4샴0 19(2?r474u 5M2 5rS4P~5444V4d41A3w2:3-vF4ӽ42||4v4׋X4w34U4@4a4)a5o5~4Y4n57^g5?d5 V5#^52-54kT5465{v5o5v=5RS4RG5n5]5N4'5z65O\5.,5F5 5[4-.5\>5]5jK5oU5#4]55U5c7565d?574@1854w4q@5uQ5Z$5793595CN15e4w15( 5W4㸄4V5c54Vx 5846@5]c 24T45sM4:4E43no422Kv2X3Gx3.4q82nx4N4cv.ᇤ3_3˴S-24೬v4i+3n,&43NSTB"2m43]33utd4oG4욢4V4E ) ^}43J34ch3|2 ^4`|4Y44Eq4@2}a443 e57544Jش4*R4!4 4R 58.5ȃ444 4v=5yQ 5|4 =4VB?5"41\4% 5r<5jI44]k35A"4 <45ʅ564pa.54C5õ4=TQ55:5^W5(+55?H5Ay5v4/5A3-!5E#l4lx5G-44[S4XZ4IG5f>((\3d1 8,4($5v"u34yG4i}4=5]C5f 5Wr4 34u繳 G4"<8z3./44D421ڹ4P5`4W4@'2_4 5b4%4&E@-^8K]34zr4zF4 3 3+3D*"4PϵʇYNIX4w ;!ׂ>%uq,yIYy\ [:)~{BF.䈵n◆VOTVkbu_/-ôRKX4IH=A G1Vs"LZeYK 관=+'0Gܴ_۴ƃ)J̲< bh-4e2%<z4`^hx3P//.yqAP拊Gꉳ4ϴKn\ʴ꛴ j0oW//3t#NE8>% 'ۢ9Tm?eM;{[ﴻ'sD_張OȔt4YTuۇjQD9n鑣bε૵ԥ뮾0ik[nӅaHk0~¢y:#9Vr:g&I󇵭y-$oYf䁵;RU*\{n~25GP /hE=`;:ѴK0Ӵ$~5\7޳ϥЖioA}q3Vz{< P3i3s4*4)4 )4;R4U4*3K4q4괳.3oW(V4Bqz4|Uc47ރ81V4^ʹ$2p%UuzƴRm8b8,ooZGj"9^DR^]JWo6AB8#o'bⴟFX*77|cM$~b-. XMfDk\ޜN,"%z=?z=A9zP`C JDT0v?3%cojy4'CP83&?444o[4{444U%45Q5T4ʰ4o4Ox!55444,5g 5"34) 55Uđ4ʥ4*4߫i44 45G,똢3ݯ4`J5Q33+3O4E 5%]d4.41(493ǩ=0x3~32pԴW;CvFe*H_ bi>saI0B+e}@+gFHg]I7ix*1z98chnRVp)_6I:DMdдG.qִ´Xʴ` 볕;R9ƴ$u2733 ɲA@3=T4+4E3644q5 <54_5R5uc5TP5)Wu5u15Y4Ł55B w5pt5855elx5Õ5:5`5 5HN5ߍ5H65jVo5~65D58u5L!5=z5"g5qp$5m5)5O45EC5E85o4|4m4e4e44894td4%3+{΍<3à )G31!Q!гjb 9JHNd}4δˤ$j&"lbG汶1Ű_gGJ40$ڗ|_X؛´5z3RV3է4;4m4Q?44!4 3ò4344Q4#54p4v5#h55 K5[/W5GB5=P5z50l5:.55z55U55i5(555Y5W5q5566wž5˥5C5`g5Na5L5h5n65055515ː5Ԕ5{o57q585"^5f,5˄5KY5G155hbM5R44)4de464;Js`@$x3dH2봿át e@hᎴgm7ryo~_7w 6չ$}BF=>?Y8AxJ*a~V Ce%y1<ZAkՅ3J=۴Ze5-v9 72x)3s 4~B4#^4l;֘453ۑ4:t5@)25ׇu5OF#5L5 5N755V5Gp5y55C 5+A5526(5y5^85r6t5*5=55L6n5`5}56,5K555N5E~55m5&5S5ޭ5ɿ5s5ط5 5{5{5";585T4~./54k4H55}424(4g0KmYH1ѱ5泛]SIѿq}}[ e6\% J*Fat[SoyT DW~a&D߾^C_F#nlW6ukN𒜴$2B2:9Ь:44043I4H24{444;5O5h7H5_B55q-55L05fb5j5y55ED505D5R6U5^5[55~5BJ5M@66i5ޖ55g5<5q5K55}5A555E¢55C=5(5G5`5"5輢5]5\25&5g45B4'3{(4i`3Zɳn32B/ \t++mb;k֊;䜵҂(`k?9> ȵ8µXH ~Ka P*ODW󲁵7:J'3 <)}A3ŴD(3":J[44r3PC1'4I5g44"'%54f4/55W5 5H5S55WW5bOe5G_5ȩ5II5x5[2505\5ʾ55`5Ԓ55㫧5N59a5et5~H5cU5i,5FC.5ZE5544~U3cZU-\3BVi۴V𴑨ڴHƴ ˴F6 ZpGgl*,񞥵Fµµa͘@빵XȵsgյA:c T 3<ٵeu16ֵ\Ww õk޵Kĵ>o |go2Yd8>2=`9@/"C(AMM>4f3a4cZ*'U454045 E5:$59M55ab5:b:5x5[m5ǭ5`5g5࿜5D5x5$554559X_5`5\5N5,$w5ZS5w$5Aa5^4 42u3TQ4S+=2xfJ2LۣJF=&B r_C5y͵ףz,õM CFTE? T #>S># F57!YC 'd3Ϻ)<7,$'6;yCL2!%)L.X=, Ksi޵󰫵f=n \jR'^66w@Yγ">4`4ڽ4W)454o*5U55q55A5KA5Ya5sK5~c5&5555zy5p555L@k5G5f~5/56"e56595n4djX54`95854vf3. QD1wB*&"pմzW2졵qs᥵zmڵC̵*˵6="o VCem,9~ . ~h"UL-ת޵4ϵӵoZѵھ癲6õŵ$]nU$#e b5 7ge<2S$g30w3F2,05m4ۏ44F4*4 Y 5OD5rOZ5b5oQ5A5?5?j5|N5!o5*[5s5܏{55d}5Y5B5<5J~5giX51Z5m^5a:5L 5х5WW 5"5y5r4Ӝ"4-4ku2#u[Q4 7zNC,ZBMރO!]uT?a)ݠgյD̵.2oʔA = P' [nYjJ"浹Jݵ,Oεݢ۵iǒAY\ZqeUU!+<+UOҴ@T*3aa34y-4}28$5#q5f4l5_X555R5{5S5Vp5UY5ry5ġ5595y5ǜ5e5n5-A555G5'A55բ5N55+5u5$G550155N5A5bֹ5p5]5)4 45,5>4³3!bց3y2`8DZS@suÖ7 +NI7FQF%V^+޶HWҵn׵}oγ!bpvgbÀo‚鮵MSLC4s"LkVgZ04&״a-~δ\JX.ު4($5A5K'5"54i5SV5;d5:3552ê55S5b55575zE5ٗ 6$&6J6(m 6H6W 66av5p6&66T6 6T665Y75>5 15y55 5F 55^55ڊ5e5!555K5I~5F5D575f+T5TJ4@494Jt43F4ML4p/thg2r*\C5?rv9q*$ ; ?yg"n3~55^+5+J5-5s5750N5=EU5&"5K\5K54554y3ݬ474J 14#Ĵ&Se9}z $/^ qJ0>ε Y@tԱ]!Tmg`KX eBT .RlAgF ]|[k5UXʹ~ډմ灴 5"]Z5 ۋ5lo55*5Ǯ5ak5~555!D55[5\N5ߊ595|5f5X55x?5f) 5(4YS#5N5Y44Z5P4C442{ 4b404A1LHd Q3@뉴Z]ִr랴7?ֺ5vv]Dmszb쑵OMCsɵ0id]yC鵌vǵֵC㵌ɵiHD൪׵W}̵[wo6ʵ(ʵ1ĵʵ8BNð.*9i&Դºm2:a4-Ӆ3v943v5x 5?5 Q5l 4 Y5K n5,[5~c5O5@5Z:5r5SMx5'ˀ5{5<5 y5x55]ٝ5Cd40v58g5\J5Q254 45&5 4^0/O44y4̀3kl00VSд  /f:jOh/g|N/b3y锵lq656J[е0澵Xµ(bNdG ǵj䵮µ ԏֵu+µL!µZ׵5ҵص|}qC#0Y _v;~1YDDϴ _´d^Fy . 4TiZn4擄Q_4SJ445#4w55èf5RO5=$50bN5 55 R5r55=H5h5Oa5̓5.yw5P\5l5Wz5h5P5Ή5|gs5Q5&5C5]H5(4w-4`4^3214մ}관1~c~FGXyBYԈ6Q6do3:f\L Qނ)nEu$-ɵNS^]ϵٵ:wL[ ܵMܵ_E*ɵŵ$,2AΎn»NhuB - 2<>O]p33K2pH54d4'5M4aqJ53nY55x5;5!5T5E$5.5 5ߏ5W5^ 5䷫5I5 55q55U.5ۛ55{5t65p5}5r5555k55*n55535ϰ5x95Y\55š5 [5n474V4W4{a4r3 4-w%3 ҄ v"gar&L*q@ fq3mUy鐵Zʵx'ŵv,ڵWcŵn>ץ.M9ؘصRUvtluV@jd7\"Q2uZy3[ϳ'D45358)54z5,r55h5N5K5qb5G5͏5Yt5d~555d55,\5B5pF6*5i5`5n.6@u5ʂ 6v6w\66Y5[55%r6555B6Q5;5ZB55=5p5D5К5tg5[5(<5?5[?5n[48h4U,5&b4K#4Qv4W$31: BU"{Ŵ/ f,BƂ1,x=td~6br1n{4 :sM-dumꔵKUB]!D.& ^o2'{4 cw̞ ʹv-9c4i4uL$4g5y4M5{a5ݔ#5D5Ȋj5Гw5{5K5t5}5p5 Q5:5۾5Q5n5x5/5#E5d5e5@5L5X65/5O[6K6M6m;6ݣ56z 6z56'55Z5V5555{5a55&5 k5]p5`s55 5&52V494˦4g4q3 3 n%i3?\`!4ᴥ2mӴxƲ,- o#LiQ5Bմ h1סFo1,EH´;kvѓwt6˽X4&544\'3d4UN}4 5G5W5M5V55+t5bz5=ҡ5?5׳5a5%6Q68566 6. 6 6#6- 6 6+ 6uV 6+6p6.6;6lg6J(66X 6C6Z6T 6K)5656f56߉65G` 6565555{55Iv|5H~5KƁ5'e5t5.f35J25ΜT5F.5L25s4YK/403|ɞƏx0}Z)غ_@U.lvDaP5'#@o"f3δ1cCҢ}ǧ|y3ܸ*Ʋ)E3LU\4 .>3.3P4;3Z54SF44UoC5y5o[_5.5Iw5/v5V5!5585x55C58s5߈5755"5I55C5[66jS551K5T5%5R 6 I5,5u5H555~5I5k5%535w55)5A5*5|55P'5!5Qz5U55uڴ4/2N3'*#ﴺE"Ӵp;I‚Vs?l3Ϗr}R~ȅ⨾ɋUǼؒ nZeXݦ{tõw9ɵdӜk̤^ɡkG: ~-^z'yqڴ%3k44s2M̯4p4)44P4v4Ң4_4~4A,5nj5>e5A5m5|5515]5~55e5֎555h'555ϧ5L5G5JԆ5>5ư5g5+5j5[5,"5w5m5l54-d*5(4H;4?4:"^454N{bb 44ʳ3-9U -CY`ƖpLvOᙚ.ڀ<.ĵ컵GյuӵxS*ر2ʵVƵi[Zŵgҵpŵ!µ8ҴFY$$)c O#^ۓDDQ50@ k?߳qfh܎ X紣[3he&4b1444(*p|4sv4Y555nI5C5͟y5D4g65ql5>5yI5wS?5K5G 55`5m~585[w585ہ5265S55d4=4"4nFMҴz34H#41Ò ZQY{߿UlBVݻI)ܨxNŷ]֏ʭ5⽘G*Zõܵ!͵/ߵDGZ&׵ѵo+H[}h .õﵦcşµ﵉$tʵBkfߐ<8Y!OL5 ŴE3 δu;AL؜]34]3H44484i44`5P4"45DK55 5Ǣ435"4 534?e4ue384U5<44WB94 ô-C 8AQ+{4ƴ[Irvwb[-Kote^׵Ȗµ,^dB5䘵&oص2媵ŵ:gbŵҵFߵ)W赹ٽʵ`еmh*gAAԽ-{ŐËCm6B/* Z݈YʹrN8T3ͳx~uKg3-x4{t/43s4X-44`d4!ç33I4:4_y4|34N54 5c54J44_$55fK54k4ʬ5O44*54㝤4{5w654ܹ2/4"G43B񓣴67{KT4Jƴ1J^X"D=N>`7h~U X%j'Wr}aÅo9b-ǶxfjHmvj򙵶\$%ZJz_[أ?XFpvFµbAdc g9Tr["F  J\ͻ H?3j@1Z޳bNs2?6U4 f444}$4{v4m^4`4e5-5 5N 5 5*\"54Qv<545SM5 5M4\45P4w4n$355~4259-5G4z44p4Xe4&i4Y4j43y4hY4Q4b33da2a84C4כ4 4433K|N454%t 5&5 55Ԣ45 I435R5n5O5555 ^5S5+T5DN54z$5U5 A584wn5hi5k5g565"5!=5qh5~55Bh545%4.52 5ѽ4@V5ԓ4 44r5s4`44y5͍44K4444W42єJ-)4͓4Sɤ4)Q$4ӳ2144H4}߲2OdbH34ɏ3'L944y1ȟ3\4SL4| 54/u4 I444FM4m4&~4Wo5&'34a4UK&5q@-44734Z44PH5o5oO/5<4J5.V5G 5d35\%5,5t 5w`95>5BZm5C5o5iI58B5mV524|54CJ5FM5a*F5|H5B5z5!0L5K8k5*S5؊5롇55@5f"5gF5&565D5a504 m5r?5GJ/5wg5I~a55\_o4&@544^4b"5e5AD55»4ES5q5&4 5l44)k#u3( IV4nK3M9444 4nՏ436]43ŏ34424\g4k 4 4ѹͳ84])4]a4'14r4|4 Q4'a4?4(`4M454ӎ4Iy4c[44rx4ָ4/+313244(D4GS45b4$ 5! 65@4Tf4i53Rܒ4ܖ44^455|o575A15544҆4!5 4e544O44?5.Y5 5M35L$5K54p45%4Ź4B4o4a 33 55I/4߮4D4R3[4*7N4L4 4 5z"495l4455QIg4Ǹ4445j4d4l4 4M4j4x4l95*55a4_5s)5 4Z4[u4404Ң"5ܜ4g54cV4w4@.~4[R455M4:5&45X 5TS4_5 ]5hN5X?53 5s55M5:5'u5~52C5Z4J5055O4 45@4245L4t44#4@p 3X 4M4$4v4a8434Y}4 4ֻ446[4G%|414sѳg4y˳p3>4_ȼ:'ֲ64] 3/41Ҟ 2E3F3=A3V312 l334ă4ey4y4u3 4 zRYa4y ˜^ #4U 4ΖV2zQ1{i>>ژ3.*44B3)4@4(U3z i紈,4Ć볮 m4yM4Y4M%n44K(4g4XS4}4 g4/%446~4_w'@4q4 ݳ84i4W4)4I14ٸ4e{4[h43K4fd2oh4iL糄d3:,{\dA,kW3Fsw6^6%c4Lh,mT~L)V)'$3P佳Z$݅4X34׳x2T{f)تW:n:JshWInmr\5 Sݳ:/HW om1Tђo4aA3;KY4zO0Y(2ش-Ѵ)$6; o AF鴑犴MfҴyӴ?۳fr1o sӴO%8GɹRFe15 ފHkz'}شm>aqW8'|ZSu6 jQy 鴂3_ +Mo4  $p w`sH,X>Q4! 4s0;3ȳv).MtJ="7ぴeYwzn1W.b.4d-!b ` 5׮20L{qϸѴ?ϴӟf)mV4´Wȝz댌/c3񿉴^Ǵ:WǴ6V}ʴ@b"偵p-q鴁h&]RW.v>97i%\5\_G"$&:j]. ӴnaxВX,h˴H֑洔b߷¿*l|M:uV$3JYĴd47O3]2+4zl(3_32nx 94b 5.]x)4034J4ٳ2Jx4ӳbkpfn2&L3,ěa& +d3}-3m>ôM`Z[ д/w Hl] ?/HTgo.&[{Q66TG^@֓lh 4jQzQyR FP9uY RJ}OVe&K@qgli]ϬknT׎+W$ɔ};VN wRjljn`6Mybe": ]]FD؍6V:oO*ҡ%}e,9'#3δV$fVJ0pߴ$u𳏂}oJ, $[&>JBY2t2q˴ `4.*'W B?Vb3x~ %9G ( rn)_OoJq/-Ǵ>ش;Уմ T?Ը4dȴSXFB#ִz4l7X״kf3 ]~34 gO\xd4>r޳Ԟe3Y>E3%M4V3 4&4Dg3 V3c#QӇ4Lγ3Iu4G>4+N4n4#4y4+$3R 44A5c44K4)5wP4-R4o+54Η4@44w4F4Z4QVChjl41K4Ny_ڳNJS4l3C23G5e5.|5~O5.5[؆5rH5c5i# 5`G5l5yE5S5oA55S#5534f#5}54?]4d44d474I4Ys4_44L4Z 4 44_J4Ӄa3@:4nt34\2Ѿ4ە32 3T4P4H4W0\3k%3 d3 44R4\o4 l!fo3Ѱc3մXuHQПÂ4ldzV 4MqX4Y4d]2K4!<1c4h4o4#ҭ4:v4Y44;2% 4K=954j4w5 55U5V 5855@E5ʡb55n`5Ų4UDH5*5۫3w44㹥4g;4S4v5Q4z4 54J5R4s{4r3mB4p2h>P4+!?33gWQS+q$d(lSzK  9m RMS (?:&!R֣ InqțI<;%ljz_P!,S,$ y+]w= r'gd\J,鱴uMjQ|/'I!O=ѴtV쁳K DH5MGf ЗO?+WBYM|)uJA ?.sg8X['k76B%ۈ´-BB7Ew ܴ购 ?9ôVFn:Ǿ<{3aڶ4yG %4m!& 4!Z\b&=%2nM43tAB$yN3VJI337+Rش3Sﴉ]ZG{w Z7մ|,&uĴiXE-*{T_2RIDd+l~@}c僵@ l &L(M M@ĵѵݵ6pkõ0Fxb’ǵ9еi9õ!wHg]CO̵Y(5ʵ|3ʯ7mB! y{oE"RȨOdcQb t(vH_udBb$v5CoCEb #MWsEU ܴ6 ͐ߕ60Iq24ӭǴdG3_璴t't;ﹴr!,p䴖kɴ('ִpG}16z&DJ<- $H.Э_ATyZ^4XL`~4)[KCUxcAQM= iZIfA{Zn<) s$`AiT촱sz3( V11D+*//U[k=-zޗ ̴J´͍F[3x4Iг VQ3F<4bN4_K4?4T|y1q&4Qy4vN4Wγ: =j3>g2椳i&^ڴl˟١h&`K3i 8xeSBP34VWw64f0h@<\ߴ3QȢC:Xr3]O 񘴉Ck8B9w̳Y_Uʹ^Ugش wK´>35*R@Ǽϴ@aX / x*#QW reŴ 6KѰ|0w !4/h3@43T4m|5 4q5DE#52534W65' 4(/5("E5̉85Qq5K55`J5"5K6J5Mg5K#5Q5Z5p5au5SӇ5N5ƍx5Ⱥ5 q5Z=5s5a{5nL555!t555h/5i5@5z5in555Ԇ5A5\5t5=t5C5=565h4Bt5X@5YH5A44O4)5C_3z4:5 4'3°4S49u4P 44"5-}ز4)4G4W450U4f4?S45d4oGZ2LR4SH4K64&3W64`44K34>4 J4L4W 24h844I="4`55 N~4; 5g5 4G444Q14QF64m4`5495ѫ4j4:5H5Ss4)I15l4 4)5.;i5V4,4|4,J54f4x555t55{5DsI5]55D/5M51Y4d:5-R56585'N%5@5r45.5R54a@24e4 44i{?544 545nl5f75;5֫5ԧ5s5y5.-j5G5{5ms5ۖ5갴5a55#58F5855s5$555z5:s59؎5ca?5q'5Z55$R5n[G5<5?4_54"G5`543Q4.%4X39443V4&4{p4\|4\<4bb4A4w4N+4b4:O2R3H31 n3(3(3bX4b 4Qp3v4v4ƺ4 ʲjb34e44R4A4@%4=43#5 4J_44xT4ד4 454i4la4x4R 5n:4J2H5.M51V5?d5z^Y5@*52552y5`e5s4=~5G(5NT5N4^ 5BV5n54m%[55D25gg-5ku65qr5Np5J4d55^T4C5re5 5H] 5]5 5&7'55+4t5qQ5<'5940444⮔43~34242(4ў4Z4 O4U4G4ȩ5PԺ4Ȁ1Z4QC4044gx3Ӂ.4L4@4[4ڲ464/L4jR4i{4v4Oܟ4! 3!R4EX3dQ44͈4V4w4(44 4^5u(5׿4R4~4w5r4ֹ4}4}f4@5ឺ43r4C5\65'53E 5-5h#5;4]4gO5F>5+P55O5.>5 95C5MVG5(^5K5")5i5׌P5^55Ex95Hb5j455_C5E4&4f$3v:)43^س484O4#L4 f3⿴[B3g4@x.IAsC t33 3Nv8䲡K,3*DδQ|. nӴ?34ôW\jŪԴ/ ZBδ $T伴Sѭ4:4Eߴ̰kBVLWSD ukOV)z3!ŜL괄7z"{[#ĔbgXTy2w4Š3[4L㰴362qLٳJ%/3:N]괎d3apX 4ZzK1G=^^f(tK`C4c#+kң**A`D%+ dE{찴pfffv(?Ú2tgb#͓Nsvґzʹ1M"S7C<2z( &ˌvJN봰n@*@HK(ߓX4,* C O|x{0]״W:Ifu3g &HB$cI&))H@^4 0VcYna3Դץy´,@|Zi.ʪ5's0\F%}WXPh W d wQ82$ C!OK& ʬ]贘Gb@*;_}:CR3Br GmҴtc$h(sPdٳĴV_2) ̴WjNOi9$ڇ/9iP,Kݴ"SK$ Z?Ѵ=ؔMRc;B]-Zu :6?H'h1̦K2=x03c2Bz4Z'43_Y?4:Ͳ43kI3+42}3/I471M ȴ4"ɳd2IH3=k9Jj#zĴsù7B&iY2޴?K84Ifs 3\K!3i+~ UԴ`x~´woشGy5BihǴWR֡޴3:DWF.ִ-?l3/aޭ3ę3M9ٳa4M44:Ll2ŲJD4ai4jonBG4%)s3F4Y4Nx4L414Pf5Ύ4Ǒ4PBN4F<4ͣ*44)4 4G<3@2tR2u4\ |+c44f4@۲3q4B43W4T,4@4] AR4O4Wru4[4ynw3K4323ZN7þ2e4x243[3:4A3Iu{}4e鴳VYV4kd33xH3E'43B4q43p]3%z)ZM3s/#A 2ُ=H 3438dKk4^33c327(W4 4/yє4Z.-344 3dz4K4 5H4EƲ)3PD5?=5:524b 5Z.5&5b%5aw.5|<5lB5~45*5|Io5<5kr4`584@.544L 5YX-54ni5~55-5&5j*5^5Y4T4}+5)!k45P5*4][35]4r3i484d45x=4y4nϳ.Ѽ4 4 z4g4K3J$@4 5|4g5m4&]|4Z}35wCv4I4s=u4m4r*I/54G4Fa1 n4 5t5444Ld48%54%4'4834"*54=Q354i454N 5<54C4j߮4V84Rä3|(4= 55 5;h3jD5taq3d 5V24464a[4n4#"50aM4+5`3154u41H-4ݱsJ_4D4O#543 D4M75K544w4T4G4T5~3fbu3~B443Z4mZJ;$p4=B4h3¸4'Ktm44f,4*4p1Ld3P4@qō3R#5HP3}_0 234m3]4E4ao³4[3\4W3Yic[4\3}гHi4Ah3Z 44ñk3* 5V_4q4I$544h3u64'3M4w 4Z54655/4 35یM5:#5w5p4der5P355y4܈4:455A4445"31q4}B44y 5P4744A484^s4ʜ4 3=414v4J4J3o84.eS4ɜ07Z^VL1 4^r^7д;*4@ߑ43N9Az9!4o{ެ+47Z-3$h41>L2n[iz"p&شRZĞٴ!>Ut_kPgV1Do4: y3nj/3|d4 &3 ״-qoaD!\ƴ︋3&%4t&j3Mƴ߲*D!瞓3X4 ׳g3@4;j 4ϳ$Y}?ı>胳L+4y2iX3(4݀@2 )4;JSG`BQ29S42=1%7̴ؚʹa Ĵ;(ҴMI8d+!3 /Qtkմ8*BǞF_{b {2nL}X৴9 dzRKIYL17F6Ѵh`Ǵb <Ƴ ´ɼ2C˴udތ{RNhGKٸ}!m ѴDrY&[.8阄Lh3xjiZ;,=N5^YO޶qat :'kc% ,+կI \F@4 M4ôS9o To@!RU~}ؑty,4o<Œ)ч1٧i;vJyږ4 SI}*4 +<3hw<4ˊ0K et6ah񳲛>J42LM4+.4J/&4X33r 4O},4?OD(43Y4PMr3ݝ^jY1_3(؃O[03'd#@8E45C$DFs3^´ĚVk1@ݴGyF-3 AĴ⩳4<4M㗳4좬30U44J}344T 8d44XO4U4/1q=4U44PƳ8:44X4L13`@߳313-34gZ>)u4@~43+4i434g 4ѳ0i33{4Ҹ4`%4335yʭ4*:4d44454z~4Ӂ5NV4c4F4> 4:24t3 5Y\3d4lN{ Q4$43l#)44|4g3W4-'32 b3>|^4x2dh4&Ĥ024]j4$84;"3q 5|4U3Itr44$444,4}4Ž4] 54 4V23h+15kL47@K4F)54O$4rx4%5D444`2434JY4a44I44v4s44o54G>4TK4u4%P55I=4444<5X4,4@زnL4+5LHq4̞4Gߤ4嫽4;4Og44%44v4es44nFD444hm-4ud4<.3Q4;4554PD-4줼444EV47`B?4:%3v";ek4w.4r}E4?K2Sw޳4R2k32o>3sպ44[24 F344~ͳ]4#4L׳2C4u3.H3t3z4&64 4[5/Nr42WE4RU5#25 4^N54*O?5} 5*4b544W5gs5Y44L5}Q5A4@5G=05C5y(!5-5 ?@5,5m4׳B5535 55F5:5-5F4JL57t95YA5p5a0@5Z?5x2n5r25_M5kJ5R5|[15S5 255>4b4D5e5g 5M"5@5}-5d 435Om54);4P4 4 5ͩ4lY4R 4gPQ%5T44ݘ5fs5gU(55l55k"5WA5_}5@5&;=5Y5{)y54Wa52Y5Q55j 5٢J5 %55+-5g5\S5i=.5j4444j643 v41445=4͡4WiQ,4GE4aS22o4Z^[45#424mW4 4x4[\ʳRԉ4^g4L44Qԥ2ߘ4~T515a4T4n2@4z\4 3%#4P32>4o2 9h4A48R3'3+3̳34N"K43+3_b43G4?4ևʲ5p394 2A3x4l4O{ŬB5O#44z 544F5q 5a%4q4W55)45WGB4>4I44@ 554僾4S44:R44u}4[X53 s34MK4@ 443$4[|33;@34Ň4 CY30ԙ320N+Ol/4.4%o444MW㳫05 4 4\44G5,4;5J44j@46K5l24<4d]58j4K45?4퀣4߸4`%44y445Yʒ40%5٬5]5L4@5545v44o4dI535w 5B45464Q42d43'34,4KId4Vd`-_44<*)4=tME)3i;4ߠG.3V4 ]3RIҴf1!I\KquP۴[UH;]j+ش9V1Z`V.'´ ȩq! &/klH㳕[#3-,섭 43!xƴ):TχzL1QThʹ@3pךC4*%T4:G4i4nF4)# 2q-4 4l4HV4E44ſ3?5o4o3n454v3~DJ4{Ê4!4<5je1eS437d44M4RU+4L3 44̳S3!n1Rjӳ{7/źδ/Y8գ˴j5ִϴ*+FдߔD ס;[T_#GWPaދ#1$G)-XfW!$e#KKV~ C$ӷSEOd,n6*'^6>Pۄ FdRYr8brz4dnȴqbĴts۴J>x% }PqQN3u계a~ߴoIi5AyOٞ#X0O4Bɳp3dG1u4z۵PDz|v 3'e 3C W4~)b&GPu48*>״WBR>}$#,C F?4 ?ݻD^:kGi O؆4*P/n4naXQbL[X1\SJ`xߴ<IdkL 49Pip1cD3Bח.c ɟE㌆_ͅN擵7Y!˨[ǵۇ&ÞIp͵QB *陵ۂƵSMrUzUG DwK+7`)g?)Wblôm~մ)E= qYoY:̴ 崏*8 `U?STZ$  $rfQHӝ` 5C+ [nV#ųɒ4kߴ1ܡ3ִQN$B̴³ 30:>3H+N%L3ϴ%3! ]O ߴG p6P!:$?U[-Yt}4ѽiD24OfX=,[o wBW~[H4 b7ś&vpŴFU|К |޴ ,j앴WA)t67P}tcG>ɴK\3Wo3iA)3b#K45Œ43s44s3E4ʁ4444 5_5a5B434n555 5&5=;4T15X544{4|)5Z4:5@05B44445C4M/#F2p4+&ܡEA2;l$ƴ9$شh󬲣Hd7ƳF㳂}ef` 3w0;wgM,[}BI+{ +?r(.dWG11({ Se)kd;-]w!+j+-Av)i9EFMŏ^ 3bളx>Lô2Ħ3rI_Ŷ4՞ 3}43[3cU4!4[4wY4+;4_$5s#5qϘ4֠4eO4G5| 5u5P^k5c5K%"5J55|25494ui5bA5~47E5/5W5B44{4x.5:45|3y)45ב4z 5L3V.3!*C3{4c3W 3'W4>R3Jχ4;YųH3?l¿lV12|-L2Ba?ôZ`]˯˴(#4x8Ckt m VS)bπjnt7(1Oƣʹ#4ƁɏC;s54&4k3|<ڲ!-3z~4U:o44}64t44VHv4g!2~4EMm4yj5z:5zE5)45L954Y4 55O5$+5a4K5lN5'5G5nT4N5t5ң4B,?4L/ȳ4?; 5D4yw4_ߊ43`4#4b(4Q{4eB)4M4V3ųp>q3,N21_4:4s/6a4te2<ŧ/3sS#%{+s͘AƢ(%@Unf5?e'<ײ ݴa^ެ& lѴJsѴ0 ۧ|3֏ͪ,Q3t2|`2`4N2"w#H43X54pE4ыt44M44) 5R5z35~35#55d4\(5.-5n=4&G50y5mMo5p4Y85`/534mT5v55 bH55o.25ne5<5v&5W65`55/5TM5=5a>5wG5λX52 5ZG5A&5N5,,5B5[Y4G44祓34 4]e4/.Ћ H74deN3)i .?:ۚFC tNʴciִq%.ڴN訴jӳk,ӳ=ˋqEI鳡xy1ݴ ⚴߻4 2,AVp*32yn6F41zC`]46v 4^>3_ @>4/~qLf44%t42s4_=4ߑ3=J4@͚4<44H!4L5Qܩ4r4I45,25'44 /5um4t]5m%5z 5i5%r5!4c5*&5ȴ4W54Ƚ4۔5,5OM4T 544KX5G44ʧ4B44"5)444Ip3y4y1~4)=Y5t4eR45>jȳb4ڵ 5^4^3q4u4<43A4H3lǚ3b53^444bd5/l4(5g4B4ML44?W4H44L>50&j4y3h׼3u!W^4`q684u4 `4f4sP 5j.44ߐ4]7p4y)s44(5'5`54"15%G5Ƀ554(4A5`5H55zk5K5]5,y5 t5Ƈd5=5N5L-5%K5<5h4|5s5LZ5 Pw565PB$5KU5E65*=5 4D4,45O44!4|45 55'j5544ۏ434^2Y4>4ǵ5nR49Dɸ434FI4+t448473::1e]=a}22]mưF³+$ bδūOHд3o4$ʹ0 }s25Fl =Ĵ>tљNJ303YĴMx,!ė 4ኳkm33l3ȳc׳4G-44Ș'446j4赦4-4594t 4Z4m++44d4 5e4 4d4h4B44i44 -S5455"'5.4]47]4y/5c54f;4@3_4ά4Q434*4Q֜} u4eT4']4B?2Bt4,3O<ܯ窴KJ2é`oشݓv3;ִrL崍޴B|M  @f \D^b[4i梳 >+ :8u: 0m=e7d|MEʴNMk00ܴ7통*ŴՂ$E˴J7-ܴW*Cط ֭s;ִ`Q"o= !Mh,N)+1q 2_'\\C?足´dzss3 w റC[DݴʹǫS[FҰ Z덳s4Sju(d ۴kmĴD=}ѐJcRr7^wm+'ٴOԴcFaձz  g4ޔ_E1eu'_&Ѵo`F}ʹn$[?R=aj\t T$LyB!Դ`wkm<"ojz`4^q6?3C:# D46l-3k5#+5t5M5[:4ۑ5Q$5 /<54l5ܤ4V^5ه5f4E45*&5I 4 584D4Ó44x4D0514h5. 5 *5C54Ȏ4-*5h5z554c$55'4Ip4EH 5O-5.05T>55]55/5rcO5U55̭545>pY5{45'5]R5BP+56es5m\5!S5k55).5np5s!5 4.4}5H5,5ZUg444*4W5`t55 5]_5+)5lF5f/5842I5yM5$5J!5g5:5E 5(5r%5?:4Y3e544+5e sI mkc`3E8 W|n3Z(!U:%d \ Z  41m4+F33dONA3w 1(Ȳ1u4\4}24X3i3%43@3|3tu44u4 4e4o4v>4L3PF?}4PAHA4g44܉3^3j4~L4&5[Z4&4୽4h4DŽ4$5,4l4{u4@ 5}4:)40$5*4-E439ឳ{4oN4ڲ54;34֖23T4<0Qm!䳡*^Nٱ Kxմ!==fδN'BѴ1g2Y73]p.Vմ=t6H2.ae㴚 洈Lg_?l3cXͲY4Դ$ 쟴ֈȴ6(Ѵ 11fD]+lضD472J1di5KG3޴d^ 3ݎ<ɳVV_/g|D'/|n{S{5StKEز- nǴV_ƴ1 Ntb䴼TqZOcId>)op<\R]%ⴻ1,DM6xE 4#g{4!UWW ~$Y=H hKCƴ5 R #k 8P״=jѴO* )z?)J´jشGFh[KkZ3#3A&@QմYnijb44h34óY"o3e>ݳw^7g;cN2/䊴ro]CTꦃ+ʴb5yt nǴl!=o L%CP Sa0%e贫Rem$Iȳlaմض3zh܆fX qmf"[?J!]X5WشRF"Zr ´r9ߴ c쳓02ų n3ڳ?EŴ㥳44Y3X: ^Df%Ш&ghF\Zq2`9Ha{c_dz𱴀bD{{qق7FrT~bEQ_} ڲ{ޱ2Hn0崷Lz/lwdX6̓13 ϳDxj3eST̳V{46E34 XN3̞4N[:I3A:}3=C3ە49 3yk23qM`3VFdvմ` 4?̴K޴C)3 sbQÙ0+$y[G44/4Xe3L³Ǵ*54jkzŐv>-3%D93Aܯ4V)3$4=ʆ3{3Q% U2JDJiE4~!N3##2´:T:ȴLԴ2.gm@z² c 4zhWpt+Eδˆَ3e@ 4c>`RHx* 2UQÝ^pIJ` $mߴ 0k%봾 B`,k--X+$!<3,v-%ò2n36P3q,0#)3O3:2|4}px2`94a94jY3e4#n4,eH4/dz52a2L26h}4iJ4Z4z 4p4Y/4n;4k"4l2m 4#40p3$=4"3׍44z 85a4Xd43Fԉf33rk`4q^ޚAs4:u3x4~4v23S:44S~dk~.ϳYcgδ3^( δKմ\5ƴ +e$XlE1a3ȳBb0534p34W3^F4~44F434Q4455`5Hp,4]4Bi3&4l4@5444t)5 44O5"33{4*55k#4 4(t4s2Ѥ44[͔4s4^L475Z4 } 5t4i74 5g4k4H}t5ץ!5qF5B5M?P505hh4d545'I5F5ܴ4=85()4.u4L44$ 4qX1aP 5K24'f 1v4=S2f54UM4b4y4dzo5*4q3a^44iw4"4:4Sq54V4>3f3:4!3E4x<4 434:^E4<54 45+~45w4+44",4lM45*3~a444N4ѿ4334|4a442253 43(44_,564:54'484"V 5 4J4*55x54l3rƁ4wR44`<5V4T4"4԰4A44\4?A5\ 5\4O4mO43sL4Jn33i :4`4%iuh GS#3p3נ3>4^1 2Iw; V6 4 uf3eDY3j4aش`C v akƴ&pe P2@KCBa9H05mJΜOf@ $46Cг1ꆴ=U,c^|UL1|?4^ɴ4nڍ4`43hcR343d U4 pN3!4h4m44854Kj4$1V4 5F4?4 44 5՜4{P4¢4FF54U 5+4D54O4)54p 54(5k44R3r{P5Y$4144v4f 5^D4[4 |4Ў4Oa4q4ٞ43#4x}B9e5}4w*594饲4873ӳ3)3 I{4ʽ3ϴWô?߳fBj@ؽ5r >2O :v4J)'14sy3u*4V^4慑4/.2x4i4>4Q, 4kz43;5]F44Oų4=Ɋ) 4RT4_443 b4Zp54gWx4A.=5⸶4H 5#6 5Q57>"5Ѕ754oҼ4415E4=5=h4WB435E5&;5Q4\25K` 5WI5f5?5`A(5yC5;4+5"r5Z4A5]585405w5!ae5۝5 c55 4>55a5t4 5M35N4| 5j4=45Jr4g g2k+1/$44';u 4f_3$5 41֫3!3AdV4Xy ;3OT3A!iL40 4w436On>4´uZm]ğv 3xݴكRgDϴ`ʹdȴǴ(۴\ {03L3uC4+=퉳r0޴[e13>~c3hVJ3k X+~}ʳZi8U3#4z9JƳ'3I"G4vA343S03:,4[4-J3kSn3eO3Y83{46#54pI44im44&೴Vtϼ2m.4W(81!3x[%44fT4۲;ڰ3Pٴ+HݳȵFFC4D-ȴ7^Eިo}<̴3^Ptڴ}6 S70[zִC2܄i'xŴ v鳟[0ݴ|JfԴ֪Cn2]O^($tDѴASp1z~\4]ǴC곣5iʼn⯶b/X474KB3d3D@3$4LI4i㿳j4(4Z*-4Xu4 nk34s44+4B~4s$5s43d4+s 4)4L 2A4^2 ߓO/4_A4j4/&[Eo!tQOo#Q}9n $3δ#%E]3]LA-ȯg3."_S;<|3-ACf۴LZ y'w{m4jJ 65*ٞ9A۴7Iϴɗ>ӴEsy2<gC|]4[+42` 2+3b{4+*4?7f5׌4ѣ,4Ph444:4~4דּ43lm0a4֍x43"4A"4xʹ4uz4Zd0􌴿l8e44N3;=2.#3Z=K۴]; +jTx᫴B.cQ,%<(łK&jVӝ~;JbA[.GH:z^ x]#ʹ=B(pbZR4ķ_wܴ_T 4\3e``J-J 2׋D47Wڴ8._\{N3)Z3r4)vyɲ` j:T/1$Hk:_ eճ\zoh:1X!ㄴ zz7]"43'H%P3PO4o`4f4K4-!P훳h$z;ʴqxޑ :>GO³7_3@0`E-LRn0l`24J'δA=^xpűӴoı9䴙6J!y~$\W”!|Rɴ0? :WɰUE 32Y2'42D(s0qA%4D[vl=J2Rx9WS#33㒃0G3%CβBC7;YM!dlnsrqeّerӴFr^IJ2)/Qm4th4UJQ4'o4QF4[4@444tAF414N'4ia34"#1K N{h3B74d[43y4s4!ó}DL 33 21[4C+3IB4 ic43f(Y1Bg&RZ3Յq4?n3)f4F+˲ '2ʧ4O̳{33RA444s4ͽ34}?a%3P3Q4 F@3+4d4e5Xd4y4ܙ4cq2~4z4p4=44}5844RA44m-5k~4m44[.565, 455~5A4*54_4t55m!5-5d4m4dS5f&4?HD5X15|55%5ҟ40F5J4 C4{5F"44n>5jX4}4_4fV4"5i44mt4͏4144X&4ޣ4f4Z4]w45o 5$4(5_go4r4e4{,4qkP4~4T4q45{4~4N4@gR3dz3[3z=4W'ų4=5H3Ǐ4o43})*Vk4'˩4,/551~4 4YҦ49:4rIQ43'4 30k34̀L3QP3\H438{S2ڳR³zy3:#82 Ų3[G4QI4 dL!3)gȳά3%,Q3P$ IL?^ȴ,̴fS]B豴ȴD|lx fKϴ/ʱJz4 GX{*1ȏJNδ S`_qh-[(ISF6Xoqz0FKLd]aaT Þ刴o{0Miδ !Ei(36M3tp³pA1ߣ4>u<(s32ٹ`$ݴ߸гesĴty4ѡ:33W3_r贁ٴ<3VIVvNE2sf4/3;445~4 [44a53 55j4Ro4l44,U T^4ލP-4J4|'R<4Qt-3 3i\ߌ3;~D)4qW3A23R TXN? yiW.㴳g&?з0*, tJ~PMOPU0&YP, 4hʹEĴn0h\3kUK{.*?̴io^+ִ(SߴN8h쏴SICDiϴnʛh'ҴX?匴IJ~1Utų橢|״U2_ԴxA@n0Ǵԯ84۴/3F߳l\,[N)NFXJ 'c|4״^X4q[344Rccł41 1oh8[2ueBDqf44v([y3z3H3I2#=\쳗cq44S ϲ޷4VMY3i03J4渳X4'3ᩴ50`#4BG4 T]%7m^4rS˂22a4C3!R&k4̭{<ɏ3Z z4N2ֳC=@3gzǴdz31ٮD7x,4[cײ478pȴ9y3U(*evE3E4-5w&n|eE;1Z3.¥4L T=3Z4_b4'F43YP41U$74>Wԁڳ254E}I3-x 4_5&4,#4}4c̀4V.4.+5F4a4 4q4&4Av3#54B4InL4Ζ454^47T4in(Z!4騳13* 3 LnմYqIBK8>)Î3%OIT3^T׳b4+44r4B4{|44(5 5a4l4.4%43 Bc4k4d44N4a4&[e44B̌4'45k4z4$4U~5(53c=4445ݟ 5K4~3+3J5R 5s)4R;@45+5A34h@5?5Q:57>5N5Y54&4o}5\P5 <5g<55 ,5]544 5b4:.5:&5f54d4Ḋ4Y5=1/3W4#4 58334#)>44~3o84Sƴ3l_424~3Ӈ4g4?4 _4P4 5L40Tk4躳W'=4{O4z4B⻴4-KU42+ݰ*2e&v1)K%( p5zI5SF5tJ55\{5&454.5(J5l͓45#5X5t5>I5.59z5^%L5+5tG5X44#&554444h]4Z5ef4J5754N4l45s 4#57%5w 5z65L$5K\D5%r5=J5p95?5&4p4=54Z[53/S4[4nY514.s55'5MK5ٔ25/4Q54j44Y5*54((4 4A4$2ײg4(z424>94[4D4O3GG34*4r 5='5(5n$4 5ʆ4hP4D4(4_y4so43F*5X{L4"{ڳ${4 -".3i-ͥ 2~[4c.(jkP2AhA-4=wؕRF74/ |+&4Ǵ'~ϝ>:;t 4 %k4vJ3Zͤ/2? 4?43?33'4i4ٸ4 [3 3]244W'84Ͳ8134ly3+ǰ32 4/x)4,3'4P 5(d4>7P4!d3v=2j4ftz5ˇ4.fm496]4:5G44%۞2U54K|3tQ404Pn4(@4q}4)43!G4G4J43133.ԧ{# 3PnkcJXK4*ִo{PQUo@մ˳ ;围31W+l%xYrɘToɴ12a .&Nݓ'7 m/3XdX0 | O Դ0:δ L۴`Beeb =W'yfء°3Ѵ9`ǽ0O'{ƴ{(dk5ݳQ:I48,4SJ9!ʕꆴ7 i‰$lŴ:`43Oҋa4Yڲ+ 4+4h3Kx4:b33VZ4Q\4#4E4i4M3CX44`E4\4~31CC =ԴK-3Q2?93?Z ve]Z2nbU;Ǵ.=Z_\~s ~f"􍻵*0d?130D`L*^3ZRY HA%>Fc(㴐[<~L%rzP^ oƳ%K.ƴȴƱO >ʴ<.:*۴ao Bm ´ 5=>*7Zݼ3\df\O@Nó׫[䴻=HkX9*jfAhbwߴ|oWРwm.1ʹ 8_U4ʳ' ,qu4^9 24XFN Dj/ d׳/l4q\aJL3xn"Kwb1ߔ% pȑt`RHi*&&`4{Cp4\L43KOZ2MƋ3IRԲc3em҇U4|aT%4N3l&34l43#6z4M3W#~=3J91<(5&[T54303*t4;3Y?43#523.5R:۱2473 5"48F4^444V435444~L4 7h4qx:5Q'5Jh4(4C44 T5%5Wݮ4=54QB)55綈3竿4+4ߋ&5k`$54NM4t4S 5444d44HU4_&5 5E4[&5eU5054gl5>65444殬44 >@5%4f#4>Z4!44{54xk5,$5l4#95D44گ44ʄ4o%544v4jA4N{4v4aЃ4h3b4!494:4_4' 53>4IWB]4: 59 4g4@W15/^55545l 5h74Q5ʾ44=EE44Y3"4B4:Hxz4F42Y34.(5ٵ4 4M4/#5u44vB45wA5X4:L5̛4x44" 5474A4)4%E54X4\4;A5W455a%4kΙ4 ~4mC5G5,5x 5$5U55p$5a'5<߽4 47ҫ4ew44m45h44m?5EO4>54!54%D5yf5C5=R5P5H555Xt5jA;5re55Z535>O5LN5B65xE5wO5!5V 54m5z354>"5J 5 n|5 ?5?5*?5Kk?5'5W5h85A?545 ;515e4ђ5740s4A5(4w5o4إ4&4c54{EJ5(5j55-5V65C85R(5Z\5Q5$5'!5UU4gH5L4DƄ5oM5(5oG54UV5Xh5q%5'585>A5"5(5B 5 5 C`5*%5gO55Y5oQ55d57D5(.5/Q5xG525~5*5H55MS5D555؁554M5im54f5435L54tz5k5l565J5 "5w4545z4ٝc5}4M5 4k4b4Z4:5342OX44$B4)?4gV 5a=34֞4H?4_c4zȳmJ!4P 22A4C֋3ٿ(4R2 G4w4@y40&O3m$pÏ4(س4˹4Ǽ@۲:Z34Ӌ2UB4h484B4[4G?#-&4ci2mz[4 Y464mI4d5)4>44Y4cnX3C 45b45z4&45w<5)54ϩ4t4+*A54#5425nL4F5l4T4z44 54h4xY44~.58 54h444ܣ4`P43\ 3W^4-4485-O4505pW44m4ϙ4Ev 44DbJ"4q14xF: *N3 >354 n4J;4%3d8xw>3F2#~ҳ&{󴾏"4*tq3JWc*A)ʉ3]3/ !4˅H!P W3鈳杳E1XYX43f3Dzo k14ӱp04\&4N3d"4вYx3L3݂4 [w]>П44o4D4rQ5 4E"5¹B5C4G44*4pG55IA5)54N4?4e4F#5C74A4Q^j4ԅ4zI4b4y72fP344b4o35ۜ34~*4l^4L;V444F/444854=4?64o.4458544414INy X M# 3Q)(/64J4O|]lw+M2-4^ʲ B1~$4δU36_Qy3D:Xf3q@;ݤHr.n69!Ӵ߅Ŵ$G7{zKoôcrߴ$ӰqS2k’w *d$,ǀc|rҴJ {V#}/.%0#A6W7ɴȳbkٳ9(2 }w+F,ح઴!(ȴSy(5`W.Ĵ}6.(:?3@ 'dJ&ڴ`63^ޛ(Uh|:3APrX=9Qﴖf(rx SǼ񯑴RjN"U,6bi64+3G洂9oy*'IRHyS%hG/*#<1t0A3Iy+"v";h<ϴ9Ʒ # B*Pے933D[O4ٷRTQ%yQENYvD8-L$|B$k?''-д .+5ɴRO_Ѵִ ִX5 &ڴe-~:>ʹGASZI2),pyo&r2zߴK-^\:X͕S*q$-6O: 3-2W0q3"z`w B&C!yX\&5np6&uH&%FǜX P.)MJDڌ{E$r2m3T<ټ.d1"}” F[ҴK y ?zִpӴqj2Kn״`$´X 7ft44 oijc-ط:{Kڴ\鳎dٳ[)4 W4f04s 44~ų-\$ԥ2!؎4>ܴ(. /V榴z( O(D+2$7H!.'*Ҵ{sw˳ ^|Q*.IE@kE+O25vWC*uc<'i-dJӴ!ڴʆCb?Hȼq$a9Qk?Ȣ4\LkΠxIEô1cZ@󳿁д;g3F(At&c2 { 4H[B ʴee4zw:Ǵd9Gztj201<131쳔94O2О3\>u33#%3ͺ 4n44X04]"43x@3B?3v4O934hG3ȑ4׀4g4 ³D45쩘3 !5x45`584vl4q4X4B;56*5xVA54 4&4L4bX4<33y/44 4wu485:5u444 5)5Ĝ\5/5F50O5&u5'5g5:5|5W255494"]-5z5 +5%55o4{5p,B4au55q75_"g5cG55O5=+55)5ױ4h5g4555;43%4*54KM5<3F55|2˦4F4U4M4-25tϳ#454?r4?5/44㓣4Ee35p(4Q4F4o~4:"554~{ 4u4/5I393^#4O4K441Ȟ4kT4^3t'1i4d4xs4*B2 4TU4V³DY2S03xS3/_44y4ե5-494t474#43]4|3}4 5m=ѯ 5<555Z5L5HF*5[`O5N5 5|5+5=u5V4r,45#54G]P5]5tR5 5U45M4_4b4w4p44rE3gE4|bl4r4Lĉ4O4ᡆ4ݿ4ͪ2XI4?4{sT4̤4?*s4Ȉ4.;4 4}4E4bQ44S3Q4&464SG4*24v44X4s4OV4z535k4JY4@54 55@3:4@#4c4m4R83Gr4;ja453%4 5:"ON3M"54p4 4|3K3Y2َ46>4F04$hM3Sw4L44444]!4,~4 %4Jܽ4{5ٝ3[w5-%52M425# 5344`4-4'5q4YY32zXy4P4̼2$ɧ <)40$R3)@\4 _4 Y4>84Lx232>i3xt3o3ᦴ94k\83֣74Y4N43D.Qs퇴9X74pk_:rʕٴI@@~'f۴:0Y2 -Y7%Ysﴍܝ3TkǴL"rri`k|) 4 9Ŵ%Ǵ3#>(C'q7ɞ婴IܴYg?ȑm,\ zNT9%-I6Te;hJٴP7,Ōvմ ݾMY,ܴ:hNE$Dy/ ˴qҴ= TIEδ, xEմ#ٴCBR '%lFr|NpSH;A~utC ,Z?5LAA.̴tFD̼s49m مp,3U8p5߱O`ײpisG44.G24<3'J"3+D3|2 ؃k32̱Wދ nɳ.;YH4I22n1BA܄fq*8qϴD s'ma;cR˂!NǴ,#״uYNʹشd?✴NnfôW3>ŴQZ|$2ai0/dW4 Syp ܴܴ)JẴ^X˴yeRj=u,&cU8Tnӳ\cr4ϝݴ@Wbf`JM4xϳHb2)۳&849梐L ח8EѲ33U6_$HL4̅]X9K3pEE4si3KB3^43郡yU2f3W\3w4.4\L/xoɲ81 ͚3Zܳ EL:Ƌ!Up2՘3vtȴ#7U4v޴"z]()״3/,3n3&4*ܲF4H7(D 2pr3B4 `|3x4U4^3 4{4l;%3Fl4J3¼7,x4Hǀ3n4+Ad3ho0t%3zv22֬3# e3[3ob2g[4^T3{\ c6 4]44Ҭ42mT3a3ڝ>1U3CwM93ش"3 aڱƃdѳV?4;K 33P%H% j04ˣݲ3ץK."dt{} }Z[CJO3T(*33:^)Ǵ42,"3 4s7LŸ2t˲8˲;863jTnG2 ﴟ+Ǵ.ߴlb{*隳DY3͋6|s ݌f`ѝ9RƜhqմ賞U5´n u34-2MK3ѴyL#jδvť*Vr崐~45~ϼ3W<#hSO34fٳϘ3؍%w2E2:m$3Mtr43kaa4g9%HS)?B4봴⤃ w(3JUc Odn3I 3W 4窲K4D4 mboP3d4R(w$SIbA32Lq4Qo&4d435C4Ò4}4Ҕ4=ܲ4;*41854 5A'5$5C55)5 )4Θ4̿4515f35 5=5~W44},5(h5-,5x5!a5><5 55P5:s5a5:5֐Q5,5 c5G565 g50E5? )5 _5?43b50HS5U5;45y35O544Q3|4{|4 N5XG 5gra24#E5(3# 5:5^3n4r6]32f3l53RH4 $5[G5r4߱ B!5e4ԣ A3 4.3FS4]45N4/ͧ4~h5N4e575ql4!-&4.4F4 QG4IJ5Y4 ~3 58ɭ44y414?a4#p3<4~34"4m4(pL43Y3x7Vݴ ~  Ewd\~o8Z<!#w˴N.3Lވwg(4Ga_^ZAd;+ ncNŲ(:1H?ݮcP|{8sk٤Xpf)⋉Pd4ދM3h+im´}E;K"4H94e` B45324C{вDA4]4&3Q'4s3 qc3dzu$FmpkM3>݃at꼳"-3{ڱ73&qڳ3P5/2/4. 4N zH4˜3 o4d}3g34L3N2L䴭dسTL'3s3i_W&#e׳" )؞ʹF44:س}+^(k޴?k53LY޳52 2L3-E {z_ݫmjhմBڴg D:xT4Bg33K44˛4P3J3hʳ P f2uѰBAo%{-x2饳NmE<'=dH{ Q4b?lٴm+.J˴x:OՒִÖ4(;XܳE&gдҸJ\_t1ĴɅ2Cۇ9h"˒Gjcó+Դi8Sִ˴sE͵jT)L34ʹ͕?ֲSW_U@C״j\yb8+c6 ̳-<ô܏G"e0޴L񖴿%P_ɂGմ0=ե>>klZ2iѴ;^^3E;dَ2T*3Noz K3>&fD3ʌ³614Hϴ7G4G^W13օ'30+yvG 3Y봽qUaIU2뫴~dciuFdz 4rŮei`K3u3GMBKӄx@LrǴT/udôγޒ;Q4(I.4d2]'ijD3353٦3?;4 3 03+([4ۖ;46x%11A4x־2] 41a\4u/4*4~3^U4J3@V#3^BYGg \$w38b3:3U>r`84g3&*2pbl2kEkY4$ "0$3흳3gw]3lR4\˴1_%3S7m?+4eƜg4 2e\'4w4u)F4wȿ4b23h3e12k2S이aM!3154!"t83x}ᳳЦ04s]M?4ڴ}½3D3l%34j m 3 v4`4e|ٳ%dֳ) <[ʳ64Ӵqس$PqkbjK8Դ5!]"3[xt+ jʴ$J~I[:;[<_] O&kGt3첃>Mwq4$J-E63,!'n9 A&4ik]VF=j!pʳ]5ʹ"7Ǵdu|% XR%S@0_3Ǯs݇OJq>!:Jִ%&dڶ%ód\Ѵ*"4Ǵl!}2%:N齅Vaųlm3r. ,X2P3*U4p4?ҳ3NGuly]3vdϴ3ŁG4u4k;4HwyG4ś-4"/3@4z33x4zk3P4)3N4m433B3P44A׎3f36|.=f 4ߠ44 34a442G4' 5X30|4/ݳ~4U4x4⯾4u05y4 +5 e3l4?4g4AL4T4O04<{4J4aC4j%54Mh4844+35g45B 5s#4֭ŗS4죶4VQ4JP2]=4tr3!83 #2C* 5"24,3C̳Zf4$/sP4u֞30D 3:й3K4\ 4Z'X41SӴ)f3_ȞOF~fʁ 3YiPp3[2a241rͣ7nѮ[{|+b4}˻q9vPg ]ϴ`ʴxnPd¯oc2>U$o_24"+߅6.U3̑>ꋳeд5̰س9S3ni3e/@ʹ;EG/VδQq$ 𶴖{3m@mk3V# 5 _ 43on4Yٳ萴4D/4O4l4( 5O4d]44z605B1D544PES4J4@4g4)g)5c55sH44x44e44 R44t4O4R5L 5~?5e5U5>5].5> 5754z45R5455e,565'5_$ 5x15j444m#45ϯ4ʤ45L5}5C5 574u+5X$5O4E5Y5s,5_55`?5CH4 4W4U54Z4Ұ4s4f5245N4b44U5{05>=4>$4呔4"44X5e 54zp4˦23v4"244TN5(5A44 4Z4}4R43Oh(3m]4Wݞ4:=4-444:b54$֒W[4F34s434! FD3= |4O4[ۼ2\)  -4瀳 l4 74峱p444!1qU44@2`4 P4KHؾ̉{yNGuش"Ys_V "i2_qTqزhxO~k 8R9V,cdŴٲdسh(X5^ "4f|[(2A 3$MX2h44Y3-܅u4'k3^4s4i644X44EH3s457H4%l 45C2C3VF4їj3g44t4`2x"k4+x3\j3 v4j[(453=3m4 ) 4}84p5zU 5445i 5 4i05U4؍4B#5<414z"35g*4404=4ì4484ad45`4<4G<841z4L7454y~4H44\زs 5U4Uvivl4^523sk1T峰?3[3j4LK'5۱4b44R44s4Ʃ4#4q455 +3d34ؐ4 5_d64N4YJ4445j3[3N!43443Az4'13c/4;D & Fץ3f} V4z1(3vPenv"n^4~54q44_*444z4c4 5r4E3h444ej4454J4{i4o;45;404̋46G3!4 5Y44lt3/4 84}4K334'k34^+5k-_4͕4O'3gb45‚4sI44J04U{]Xѩ4e*4-W-3_tw'4 44[3+64/3lY?H5A4"L4g4Q4jq44IE44م4o.4$<3~2~!]4)2~4 3 ;4 m߲bع4Zbr4'I4}>04<3T3 5s43=24vI5bQ5.4G-\4M43}=!5b@4 3N149?4~42OΦ4ul4=4|44ò4&54(Kn4/4H4qp\:4ћ4Й54Y4̢4ݤ 53&4|5A[3&4;Ȅu3w4*22ytG4N3N鴻v3Q z4B$۔:4 q4x"3.^ARyr4O3DO!_3 JI3؀X,x%(^433K|4,Ѵ4Q1~4w%_&3%լ4 óⱦ%C5—Դ^79aLEanô3! 17M}E2ė261' )˴b?8=ݴ3RgM4%?3μ4YB4%ar%})(-~43|V,4`4Dav̳ a3;#bQ 4b4(δ.v 32b 483 p4ų 7+?<>EJy4KZwᷴ&UN<B\e|3 RDS Y33h3^iu3N߱r33#.Ct2~53}t |βc33ȅwGꃴ)Vtﴹ _l`zŴ;E3$S۴;:m2bȴ`9 ɲWԷjpd`Ȳ\3c4Gs*z-) 3wd#ȴ@ #2F2T3m/zb19J㦴FXhSս' 崴˲%ZYHFfO1$5}nK _eԴ ]ڳGqkQlÊܴ̏333 CN1_22ABC 3Źh4a̳Ã'~3P'2nȴ*J 4ɏF dZ>ܿ~3H2&Xe 463\84QN4=L44_b4e!ᴲm2}K3n%4>;#Z0τ3/DpCȱc7ΜJq´ &BɴRu9e5tn9>ôU$1y7K۴v+Z#˴촌X4莴yᤴ iN : H㳈&t{Cش9C:-^|-Z7 3r-N>t21F [ӅF+ ks"@mxRrᱠ# {贠?= xODe0 o[b贜Hg˞fQ_q'26/M_^l;hd賹U`›3RRY MgZ]*l INz3lU~مVAڳ̭޴{d %4g|3{92@4/.V3FܳJзL* 겊K-z.glD#1H4AjiJĴ<èl3WzTL紴GvE[Y6M8 vGe[:3Z+޳9{N|Gqn4m3#ӲY=5ܿ4 D4ӳ<4ol41{4߇4Y3(34n44d00Ld3|v3j_sՈ0+Y943Y4<4sz3h43HW453c4%Rr3yXx4i44l4$ 3[44ê354vE43Mn4[Ҿ4(Y64cy444q4g4!r3p&4^g4H4b34N(4@R<4Eн4,3OS{39Գ䈤_q,tL4K4J4g4my04lCo0n58Å4N){H4Qib4p 5:54\4"44Š4($B494`4lݏ3x4[5*4,q@xG4({4ȴ__Śr d1,0 Rn3x2h$4€43/4j3O3+4744m_>3=q4T]4ʢ4+z3-3&G4I)4U4,4>14s4#[{l4x4 }4JR4UF4 4Z 4p4ca34Ut31Z4 54U4F4I4K?4Zh4<3444s\37N 47nY}4,g4-4PK`3 94jJ3vO4ɢ.&461Z3y4Y3fK4?24q۷2ҳ81ҳw$4%Qٴ" 4ɐYJ[\XʹcZ馔zcABMՈ дxj㴥=Oeܯ s7ƴ%дdδa2$[0!@2eò4zD階MF3a IAD4Q4p4^3zO kQ!3;u 444m2>4oe4%u|3lQ:4,4O4] 594o3`='h3r374631|4%>4"44Z4Û48+4k4s5e-3$P{44u43 4I4?x4i4d4\255AA4.f3!4Ef2 4V^4kV~435h4eY44_F40y34438Awg4T3,aR54g]3R34mI04 41"VN ;$W@J4/2<4A3.3go4j4qϻ43,4JN444yt404Z3u44El4%T4Q745*4}4sg4ڨ44494i{54<44 4q44U3ϰ4u3X5a4c5Yg4 5ȍ44׵#4N4|"5~4lS545V5ԑ5'$5%855xN5;595~55'4}4aa5 5 .5U5v&5j4d>5;-55_455(54!4הW4oJ444@F4鐲_4+~4O4[z4JC34!94 $4><3^Y4435f43 W4*C44]iI4 ^4+{4dK˱>3!4b4y[I/v3[4Ȉ4J33;3Zس-334Q`wd2"3 ܣ3%ڝH4߲W%)5k33h(4)Z4(b h4|4X4344zT4z4f҅3"4Kֆ31 3>34UG4z4v&434 I4r4q44Ql"5,44W:3p4eѕ24. -䴐 /ٳї-No03S W}uC11{4441_*eT+zuhL4R49N3$3| ;B3H@ô˴c>E84}2HTd346_|y4&KZr3n񧴋ȴ+W{!=%#t@D`qĘ#^U4N{3_+j}3H#265jд41a2`D]]/4 _ 4^/2|B._ 2ӻ3[u3X` 244K4) Ё쳿bQ5t3/Ѵ 341t4z5}4;4'XN5\賒4M4<44 34~44+5C446i4@ڤ4Ž4盧14cI3]@}Å4i4Id3c4[wH4;إI4Jų}3r5?43L3el14:`˜ D3 '4/)!3ϳz23=3IPHFԎw @$q"*GNoBbmO+>}hbNH\崝㴝R洱eiC޴~~ϴf)DR 鴮S& }> ӴU>c Kv`ִq|oF샶Ϳc޴fƴC/R"@V49gja3Սu5sx3/_l2W5𻴚д_`k۴F_3zȴXk3+u4C#4'(y6&.O'ѳP4³y_@[CB 4Uӳ~f224e33rUe_o3x>3 ?3 @I4Z4]3]44l4J6㨴pg4FW3/(4t ]4dYڳ 5U^3 O2[4- 3>4^_4awH2h᫳W4|21\ @c74ӳ33 4ט4+/Q3d=D4475\4tl413'3n*43=4f2U4PV4WK4r3=e 5U _3*4~4m32QpcͳZkנ$T4i4.U\' )2δo شd4G?̂ĴcMAr"󹖳ܴS +jCҴ>m/nô ؄ "%ܴ0o _ܲ/γXC(2ȴ Nح=3=4>6/4*Cѳ(ԭ3Fˁ4fȴڬ42U4H-Q4l]4*aW43&ճ3_"4C>&3uL4&Ⱂ>4?>343ȑ 82i~4mA4i4V!5^[4vՕ4"Pd4?3J34[@?24|3 48zֳ5 r.4fϖo4˯424$ԟ4xD4\y4,3$2x}3,4gU4zi4ס249qlm0F' &q{VaHo|}Vݴ1 (.)ۏf13]ċ#X//*kTމ"+Ob(?3;0S2Dδ82H/2`س״Gո1}IWⳛXUm!3GV1\4բwѳRsg@4ೳm13>LJ_4.㩱^3Rr4ͺ3O3gFNp2t3 )i2aֳi4394it44_4c 5v5,2H4<5U4a{44H394V4j4v445E4Y4풆2ϯ4l4a4#4044WY4 4WU4UZ4fDi4aO4lLz4} /4$40e4Ē14Ck3+A4Qr%225}"3UW4Og4Q24™33P4qS4[4JXx475t3#M4+54(4Ȣ=5S?=4f{x4e!4Oo&44{M4U)4ױY3xa4ˍƲ`495Ƹ3<:N44.5ă383FB4w<4D4gm3&544]4l34u4& J44S43D4h5g6r4V3l44;4 5l4{4@44l4`44W044Wi4k4v-4244g44  584k4Z'4R434 4 e4@&4[4/44W2+f;4F>3%3~kگx"4i 4"4L4~4s%4V44O#5%j4Ӳx`3ݿ&P`4432K03L; mj4-2ڳ̥8s-γдﱠCtSx2{೽ᇳWճ}O eAMYT2V$ϲfݴ:<ʌR3&2;+H3 0W;])44uw ka zv34kn4h384Z4.65,5̀4U\4P] 5L5mH4Ϩ5I 5[5j544O44WL5-464& 5mؚ4n/5 533;48~44l5P4>4#Ii5?"5"55D5X954g4?64T)5rI545I~5V44K4klUȳV*3j342,2WO4u4PNA𳣻3r3\8|P!T3oB2h횳2￴eǹ|P^u2Ԅմ-Ǵ ʴҜ%ȀPYѴw3K&S(]`5Fu8OIi4 Y142'0|N+tKNt郴m.&ev6+ C&S pY,NG4ZF45ӳ94Ht234җrV3I4PB4ݫ4mRE3q34[X4*54 34{4D4κ;40^3S=444:4}34c|N4ճ^3~4K45 S4ų<4XE<5F444)@4h]3zi4}4+C4D4d.s2/3Q33MZ4T44=4 t4D38 _4䄴ބ5nj9lH4ֲXO4hI)ߴ2>큳;aZ&P3c_TIf4iS#˲44*&#1 8۲|n>At?߳EBwj{UG%;O|FܬІgdĴvHuF\N3n״89 Rﴲ4؞ń,Rp^LI\rX/lOǴ=aŴ2дHy$wSfvCՁ?faٴ0O2t 1PXy'`-D=;M&?K:\a´ٿ[EgvkOJ^ 7[4 *aCs/Pj*5q ,1N0ܪn @ag^=>ܴF$ j"۴rRHծq۴O4@p)z G!Ur4fS?4F_C댳8-@&Y$ᓔgE.H3a?Fyu︴[0[3ۅԆJ jR3Jyaݳ:eܴ3߳xX $mjvDtTh8c_n%g] bdz_i#P^zL.״5:²3ߴcִÇ6AouĴT-(4(LLU´2&ㄴp743[2i-4܎β9 # =4%3tݍMj29$DoTq3X3h7*233$Ѵ!zRMfᴖDp ;{U5.3'h$tA4>I(42oX󳻢\})~ٔ4@=3ed(V4hoJ4%j3d48`}^mRJY6qu.uL0>R-™R̅N unHTv. .^| e4fΓ֣-򅳛r=Sa̴}1󲴍ִ7 gY!$4\~ 02_߳`ձ&f3toR2ATI\I | b4tj7_w3IKu[ A2)7;ѴS@43ѧ4;4A2ش_44ᳮ,3^$PD4iA4pj43C4& 554/L4bk44ם44:54q4Twa4 544$5s,n4آ4q49H4k|44]4I41R4P4T34~45=5]4j494\2 K433o!4ZQ4a.&33.}4Q4 4 [`v3[N4E񭲐R3@^4n4#y,m4gg3W42g34kK;4b3^r4aT44{4;ޯ4y4?ij4ԯ4fM5at4E94 w404'5x445Y495*5o5 5zf45S~342n4-4 u4 /4; 5D4 5745_5 [/5[4d25s4.4?55Z55ywd5 5 C50Z55V 5C 595$4M4b 5,5 4ݖ05&;555|5z85D-5H4I$5z5 5d>5@ 5l2574=5@5h}i4.-5F5Ԏ3\4M45H4O4B5`Q5/=514zRZ5D4Fx4*4$ 4K5bE5@%574L5;444[f4x-4t49 5;<44=4C18404i 5425Df.4]4r9$534g5 4#44 5z55^4h-5E\5N445o&4?2U7#4|V4j4o4o4 4<4G44)D4?5/a4.J84-ze1 4"3p4344'3)3]g4љ2[}47L4r4674!I448!>4 4W3L(ȴ k p iRЕH8랴&r\ 3?HFw3G4t-;4Q&3|"5*$4A4Ux)353JeQ4)ʕ4'cb4RH4|4<5 j3!(3vg4R4glM4@mM4t_k%ȴ"Y+.5菽4-44b4dH34.3]y &54Ǎ4>w4ማ1x:3D@4T5<4(04w 4B4b%[!Fpj Sv742 ƴD,bw1E3kY13;@(54v4&uHE (obq \%:bZ3 #30$2'(C妴&Ǹ3ϴgٳPaM KBЌ<7@>mYs:TôM7ִßiMlaŴIQ6#=G#Rѳô 474 3 28H I4K433.4ѷ4d:M4 dWi ;4V34LI),@MxN3y3 4`44H41)43>4gV44 5x34Ȋ34⊌44ͱ44@S4o 515ԍ4 56]404_0B$1(t4(3u43z.g\w3PJӳotz=ʴT~4\-o>v+I2֊4K4x Yϴ>;3TIv4g 3qjmM)2}3]3{SӳuD32-3pG\W3b{>44a׳ 5fα|D3r43/k3q4qPͳq`4436Գn4.=434F@yUZ3з4A34!4h4444/4B|4~4w&y5]t3K3S4#44c44w+4q|3`3ز1^X3>Y XH34z ݢ32/ 14Fa4'J=3N3(-3 8ų4C]34)~;X4 WƴhԱ 4sۋ4lKг64 ᵳkR4³u4UN4 5C))qK$30:rw]3V":@ʹKwNaJ>%شvpnŴ4&츴uɴZ*Oao ҈33Z;G({ν3KDe=ƴƃ0G^ִ+83&u^ pI$ϐ$ൕKF(:MӴuIд&9!3Tδ5ڳTrXa$IIbJ.%ekf7]ȟqqa^5kbgA]c֟XHj #p e~o ~ մhҴ*|?Ŵ?B njF W ޴f;Utߴ)`N/L;/ x }K>&^@=Xʴ2bvNglYz4k״d3_-`3Q`ǃ/3n;44㔁44iv4&5* 5j4r3G424I430443,4x>44rF4H\@4 w4E3e4944D44I4474 :24Xk޳E(c4Uw34o3м4J54 Y4]d1E1z3e(413 343Zm434,4T 4܏4U&c4ܱ{4!v +R sȨHқ\Mo'3O 43֜`(˧. 4lt#Ŵ<حbXpUn33Nʴ::c ;䳏t}2ڴ3Szݳ>l4V3@!W6X=4ZIW0Vjo ! 4x3 4:r4J3qza4i⍴6G8On>4r5j3J/4^u^hfuKA4L.Dfd4J4(M4,H )7b4J03>j328T4l3Cr (4|ߴzi?34u.;4fhՠx"kܳ#"3 .f2W断@.yi[h!X*is CQ@5̴z FڴiF.QNtS싲\?\a&7M2K.4-yԴD5j q*ZǴy-ִ4gb]f`49"4n4߳%4I)kT h3jTuDb Pozx*`Єy95~6to4mKE3m3б_珴3,0-߳?0ɭ8 V?e$ܐAI"CJY )ԴO^0XzHMr6:!+ xpʐM3Mj XI:HH 䳰뒲l44a4"eN3L4c*3433{'n3Wϑ33YE444$4W<4݈44E46j4r1ش4d>5 m4!3o}4$5jU4Xr;5)04T47W5 4/*4 42߫444b5<)Z5z5t4=48t84%W4_*5A4m)5׽?455+5I054ߛ45N5IW4A5)54͇25DU5Ɂ54X49.}4744f5t D5!5`5455j5@4J>5#4z4C4f'514I'4J55q7#5h05p5S4Wb5l3574k5f454c5CT55_E-533)B4A4 3? 4fh43!qF?h4?4{4f 5bU434S4 4z3g^4Ć4TK4M5:2n£4 594:Z435x4N5 54le4@-5L4R4e@4]5V5F4ߌ4и 5z44%41Ѥ4G+4 &4w44J3?54L3)5^@4KV4ʝ4(4=F2b5]3ٓ444ҁ4}p45A[ 4Tx4ϯ4k424 4ў444m24x337d4N;4P3W4Xr4444sUY4v4Y 5u564k4ܛ444-4І4t4/4V4B433($4ED5x3tm4:54 *534Y5/5D5e4,5غ4N%54oQ4v4;64IN~54p4 %55û5x445z4b44X5515I44=:5$4[!5B 4Oz4N5Rzz5G>5&5zQ4 5B4L4m5EG4Җ4jk4x>5 54P5@5%4^4hY55 5a[4o]54D4)<5-54lR4,5E54Ýݹ4%404|[44D5C#4)o3<84M443ZȟY3mw4V9Q4p4d4/44;3Y20;4[4>4f}3x4ޝ444B,4v4fh4z4904nL45v3x>/3/4-b6} 4*4[14^4k>F43hϗ4n#4K4a44ㄣ4j< 54a55254; 5 5"54/5I5Jt4(5(*4Q@45!? 574*544m44n4XC4K+14>b4d5k44G&4_3 g44r4S4R434Mb4j4 3:4\&2^p4ɝ7463LO4"dձA4;4-[2j-94373~:4l434.f4+4`4;"޷3X ӳ2H鳭 zz272*B=34iV+3q>4=E64ʏ׳&঴oAzt*ڼ3J1y#sW8vҼf-?ഭPtCBnjq1J3Դl GX4 |>+5@3jI}~Wčh{d&43=ȴê.r掴-+s13R䬣-vEp$G)8L1GT괎tĴZ ബ'%d{'nĊlٴKŽ (Z\累Ug[vG;K.'gJ4K;-5a-2 n0iM8A"]5۴v`e y-vaA.]a:Ƅk{H&m(7GB%,`"pQ Fܴjô!v VbaѴcʴQ0˴ c2Oòn(}m3}f}r5˴53NQ ؚxhG'lrLJ92@ղ ˳LV4IʹW0l2kG>zU9842%4k,,"3:38Jo;eK[cy!W]N33 832yY=2v34u33`~]8b~3(ϩ@4aڳ|2h45WŴdy&3ڲ<' 3 ឳzostH=VȠTGZ<33U434c42P42m^~3Ȳdشt{ /لͲ±F#3`3'dB#2,್264t3B>4f³E_0K2u^ +322r!g´#~$CZ-SR42*m<2z贘R׳aK4q³͈&h):״ p Ԣᴙt2:r^״ʹİ)AwŴ@Ŵ`ì xIJƴ~$Pw9|s׳DR( h l5 ôƴMҴVGAﳳ1E|M/%X"F _Gց2>Դ)å,Ǵgl8LeȴN4-3(5H4m:L34vn4ӊ:4nɈy#b440wJ3<3M4߬455`e4Ҩ43< 2(44d4f4O45N44)5B4@4'4J4Jc4~4,4E5[5255^54/65J5˯5$4[5EUh575z55^W5ݭ.5>5i45e<'5~14O4p43}l4I4,45434]4 `4"h 43K3q_r)44P3n64_z3+CP34|,4=`4۹4wp-9ƴ@!$x`5C5i5<95u,K55Ny5D4dU5454-52U55 L55L5A5$4K5?3N55ML#5j5{259:5e25?@X54a5<25gي5Jo5K5>A5~#5/+555V55y5ub5p4573@5(595)5<5;5F5l?558575u5mN 5fN>5`5k4d4P675u54U>4I15w"5K 535t4w5=59454j45ԙ4Eɘ4D- 55U4Â4>43#45C4O33s4R464s4 5]445s@44 4?#4R4 3?W4刿4}34>44B5ee94d;4*+4T3#F3n4A3_cҳL4N*384˓92,{HO3-lX2Ӛ|U3I4P4{A3s431b4x4K/>tƳ(W4,nI45y4 Du#D4`u؅Cz3~Y3S!ZZ3q:4b3e[2&M2x^ڶv2z$g uI0K44/4T.e2†4|$4[34b4x4If4L4e4N434415)54j44P5"4`v25(%4C4UO44y4M35i-5ʉ5N*44#5O4A4s4` 5E4R4G'Z5a4 v5Uf45h 5- "5 [5h\5i5o5lF5P4Ɍ4pN{5-I5]544z4$,5%H424\4U3z̲4@$~43fc4x]4Ԯ4? 3Ù4 h44·m43X&=h4gLB|(44pdzg2sêgEbϴf{3/䧴rinG8sGzؘ%MW_ƺOqa_F}EєRE;c@liyR=pUƍNф"uF뿴FyxwL޴`6x0*gJB},<_rXp~.˴Ioϴ;qj#7ϴҪ1/3Z4$4@44ѯe4@4+s4{f44oM44Y~24V4uG3 Au3QE*44*4A44_4'm+4;5֎4a۳4@44o54wx4[4p34 q454S~R5C5صT55s 5 E4k;515R5q504E4!Η4y@5#5GF5r`#5/q5ja75N55ך'5Ȟ40 4RE854v4?4 5C+5.5[443~E24'94!m4R 4(h32=e4"44(_4:wۨ3ٴԖ403״+33n%1$tܴĕ2 c> 洦1 ?$5i[9=5NO_dδ  /DN&I8B*,!њk@Y$V'5鴓Գ[}$0v@, CH(Ұ]Gݴ9VIAmiGT o5,B[Fд!"-z3Ź  fִ*z2 ﷣t4ನ6!a95@>`+`锴_&2R%P8k;@q2I1)Oh6Cҿċ"N_m;3$4@Ꮃ94dz2hi43 4\3/3Fa/3 {峮33?:4]4o<3k3f14%44p4k13eW4M34;<)x\24޻4 4O3o4c>4r44 2q4|4,aҳ 3s3:45[3C4"5fX4A4E`4rUY4d4Woa34w39$2p3+RV;C-2 H'Դ#쏴kҴw=t _2=b;mcDPAh.d;VE'ۿaʹYtg{,u1^qҴ1Dթa0SSS RӴ$MӴŝZȧഭ!8+zj鴛6&w,!^;bPu5GVʳX״q}nNC4!YW3mȴٳ¯ ֥bRԴx4 CeG4&4K4 '4.4d*4˳=檳/44ӥ4R1 r`4{R3s4g4ș'4B3 7344ú4+4034f33Ο4O44Ti4d4J3?4qs4/SM44q"1445254 4'v3پ4:Hm3M3pg4qo4oL4ɨ54441H33!]EV4dw4zڳ p4VC444 K^4vh44b4c]4?D4>83ԋ4oW4e44F2i3C4&5Y4s4 4Oa/f{˳'r4K3驅3"4"b40s354J4/39kc3ɴc4k4 W !44z3ɣD3 4cj1z4V~a404UX4 r@4V Z8²634ɱ"܁4<"2Sz/"49<+]3 3&34\2G4 554fl4x4;3Kw44-4y@ 45 Gϵ43)0Uسf. o!4%ѲX) 4o3K3R}yE㳈3G4;1@4=޴wL6G5,3.:3 32_ 64FWdi&sqʳ3{}mô\;ճ$@ϴEw6"f/y"Q 2,X٢cĴBմ9.5}:ƴ*ór-;2Ĵ}A zR0ܴ +~´ԳM`شpL4ӹx&laG{(nϳf2QN@`ۭrP7 PT4՟c2OţKTw83q4F 4~<۳]3x2r^ZϴFԴ\׭AWMcE3q#+3 l'3S̳8NԆߠ-_42*4#4rcn3R33_ob+m׳մo'gNx53^*$&4#3uv`賸pCz3ڟ2$ȳHƳ qt{V7#2O`m]=0ôB~?j괴nC4މӱǴ8`4qc\3B ye3ɲ523"2z;,3m-4zr鵡372[ 13m3(42f943S5wZ[-+4/3t 攴.BY ݑ4y UyO"d̿BDuTV膩1ȴc) `P]u2r fʳ1(Cuh޳CѴ&fȴ}g-1shs֙2S;\n\\C` L?iUJlELx޴XĴ)~7=Ѝ&M11ӟ 2u ִ鶫_]Q?~Y ̥:IPϴڀ@La */gYa K`"A'#(aݴ}r\U !z۴޴ɦe7ҳ=TQIS spմH5--R R"yiq2.MbtÆP[fp˲cٳs649j}B3V3e-E4۳-4D27Z4`44Ds444[2H 4x0M4vڳ,5&}4h2424M464Y565g&5CL5T%4'5 4p54n;553j44P4*043D]3?/4= 5H"f448Y5Ԟ344a4nh#4ό4|4 4c254s4:%4825-V4[3454^4Iٲ4p434(H44ձ+ 444HA4\33X5c4\44A7 ȳp3 Cm+4uf(4ť2'4Ƕ374:3ٳ*33?m6j4ٳ(#bϴ ]{3fi>¸]:Y(Cɴs33;4=5%%43H ĴLe/32TmbY[>$A(J>$l2@_R3y\4UeQg?4˛2244>f'4j4I'4b4~3[t2%53 T49Y[4rAԤ2AZ4z4A3444 5uͼ4)4+4f4345 4<4|4nK4B4G574j4z,4J4h0N3z4R4 +5X*5N *5 =54+4P@4 H5y5){"5씌4d4.b4q<5355'445A5XF54 ;5o^:5 5!n)5L4?5 I5=]4X*5B4ha44k44ܺ444q44|%4w35Q32r 7 \Xe4Ld1B4}h|340-\2%t44|3e5]3@3^3 3/4Of:3Q=4:m4Ã}3蔳&i޳Ƴs jڴ37 UYe#ۥR=KnB,T1Ex%vMđĊ4 ÁȴJ4v4~X`Ŵ;e9DCt,G´<=W%3Q PTq ?ȰW244B4#RUST\1:h4L3JR>41&114-3$v4?4 4\4vd44Ɨ4LC4C3-3y 54;4 ,4d2E45| 4F4(~4L4X{4 ļ4E4UK5H4l:*(54x4,4u4f5 5#A4O54 4蘼4i 51o4X4Vb44qc4W544<538n5$g65E5C454414X 54a4>5 s45&5 5:54n?44Ň84l~4-͇4e3;Ȉ3821m3Ra4@f 4?=߳A3Z*+,423y/G48,6D tfzתa+7Szճ.\2ªȋ~ :uִwT-d _!{!V }A:ش)zIDִDS9"e{HAVERF׳wJx2O3 !15rިH'L޳g6qF? $*)˝Xm7²sij+3ʍJw4!aҳ?b43km3Ƴ*&>3,4<4ֳF4 47˄_4623u~B 43 H>4=ҮMar3bװ'豞4xb"FE3"R4Ed25c4"34g4V 5`WH24bn4Ş3\4GQS443\4)C4| 4TQX/4\4&43ы4W4P1V4)4Y̊4>4<|3 u4. V~~U1>4q-04͖߳f?f{ 볚r4S|gޖI9&۲.4}#2kwD97ʒt.8%`) 4zw1<>EWjmW݌$a|)%>8_lʴyгU*˴#(.prXBϴ0u361=tQ(Z0*)>=Ŵ%ʹͿ>@״>QF~'O5#dJo"Wl:^֌vЎWULB0[z]d_t#C:Qah4˂#8TC&_7|+1(,:`J=x܏\+* RxB[VPs!|}䙴qM2"z_ֿO(0Bгִ׆&<7A O36#_d=%j33봡Y 3NO3Q贴N3w<=N4 M$4o 2쳺gk4g3>S4b=4t vE4T3pd3҄qw>׳k4)46д4346738ɴLFcc޴k63MUᠤ9'A Mcxv4Y[gKo7]wѴ62a)pw(H/ԝƴ2c.r%&џ5#&sӇĞϴU3 Ѵ ߴ\,ԥ3{ش+=,XGnLԯ4˜4`4G47F4n34Jn4 4p434.u4 G34 54 4Lt4g 5@4w-4Zm4D4SGk4 *4 B5+y3:N4?4 74hZ 5XM4Y46v4444F.4y4Չ44wI43Z44Gd4J4^45y4(L43 5>4r4Ŭ4"43:w4444_5Q4D45w4K446%L5)55vf4MX4v 55.5سQ4v*5ٜb44T4ݒ4/483u444Lj3IHв"v_Q4433y4YFa3x.4=F4 44y3Ȼ\T|4Yl"54I3{i342R44V3j5345144 4YMa2Հ44D4oc3V@eE% %B"&"\Z\eJ4a%O4F3)44U4(4X4k5'D4!c$4D 4m4ǩ474X4.^I43B3( j4@y2S41#Qi4 ȳ2<-Md4<7l33;E4]Tz\X335 _92)4's;AZ333(4!33T3R4o4d3+Q 4ٛ64-3RGw+᳖3R6A4kQ3Nݠ?x4a,ҳ2~44!4޴/O4ٳ 4E3mT2mJ+4uF3\~EK:x3x1yԗ;V-h3J($al4g=4&13k ӓ3K3ۀ23۰ڤ4.03?4D]K4Nx5Hγ?2t4O3ō2M9|3(MG33#'H4/W44\&43Y4i3S24+3~"48p4{y3ؕ4\a4~4 Բ 3od4E4x!44VԠ50V#4 I!2 44t(5G#Cz4`=E4(Zڰr4f_L43 4#x\8RŲ95Cy4v3_p423Л4F4>)ӳA.4(3ت3)Q 5t(4Q4"3X4ʹ38%4f42?8j2349KP3RóU 4M%4-Ӛ4,<3zfC4⋲ /4+40#004x*4z343+24H8]4C4+-s.ggrt@3h)[4xنU14\ R.^˴*^ȴT >3 Y 3PqՔӥ172Lܴ]m-l< l\](Sδ$ᴫﲴ>'3ڴ>ⳌҴl৴bJz۴WE/༄~2t ųzWT#Z4!d!,Uwt"HnC71#_ M=d:}|8h F  ڽUs5/ E`C-;7>Ĵ =´w.S=1'3{Nk(ɲdqDԴ B燏~ #4|}ôbrK&cj33[m+45l괆2kGeU%2|)&xjM2 x4:V3E\m\۳M7442'uU4󫆱# X3]4ZjÏ`3OW3f4!a3DT2h44N*4<4k4)ʴCl1Jf14qDZ4ʶ49uf4ҳS *3AJe3+e B_3'4m;5ai X4 _4c544F4Xo^SV?\J"4.Z2~9PJݳ_;+vy*KԿ߳ 괷]%ƴ$OT WeRMa $f`1dnڴ ) U’ u# gشy괜E'%̴_:ʹFt*oY:>5ظԗ;2Ia#g˻kҳᴂ&xN~g`-3;9t43o|޳RñssRTK^Cqw@i4`J3$vp34j/43R3pd4e ⳕq m5d-4u-m4\>3?4P54g84!o474434434VS3A53MP3[3 4(4Jޫ4Ж4{4 5\)p4ܔ3!#H5:4}<4m45c4 q5M5O555}5.5H4(4C54x4q4I3dr33]5I}4TȞ4][4&5<Ω4Fv4I<4]4w458;44U'5 ̲25 4T4v5<4F4 14n\43t44Zz$4ܶh44w|{4Y4lK4C444+(B4;4,4$2C4j-S4m4P4iG4<3?? }&(3V;F49F3AR=v]/Ge|F=44D4S 4؄[ ;h3H-wpǖ3Ѵ_5ی4(44·,4x34\>4ʔ3W3C4[I 54 2ߦ4J3ƅg4744%4-447t}4F|4ųl4"3344R447wLs%󞬳MA|H8s{4@R234U?4j'W4ET4@~333K7R^,$3b/5U54C|14s3d3ձ%3^_87i\|3Ǵ ۴eD>4Ns3+B峳/-3HTy4%4 REHAC_*z4a'w*3ިm.^2]s3[;ó|44͉4~'B!j4{PəU34_j&ച3bkQ3=3\:8~N@2LsS*/\41f64=3404[ e3.3oD4<2B4Y4!:41P2E4 3[TM{4_‡4)2.44Z54l3V3ʸ4N44 43'3dK}K41{45oQ4%P4-3ө4_4L4 5b74}04j$5!4*k!5;)4"4n#4 i854<5z5 pq4^4V54 4z4ۿ4~`434< 5H5 F 5ܡc4:44z=5V 5|m4S|49444034E45#4`5r54u5U+5IG4`4h44O5u4W;5 D5p5g5* T4GV544(5^<(5MX44B4f4c!D3a945I34s4*33h]3 ф49o'4*b;4j4JU44$Ψ454I'4(3|i4M4Oɯ44>4ȏ4yo493;4F43dd4Lq/4/M4V4y逴]d4f4.6~84E˲B4|1)44O4L4d?34=3.\3a3(P4*E4(3;I_#\4442a4c445<4(P4!X5W5Y54ov4Z5}N*5F,4x(515R.5[5p^5Y^5l,5K5c#515gE534|O5z"5x^5?35Y4 A54;5n8B55'f)5$ 559!?5gs(58A44U+5F`5 5V4-5K35:t5" 595mb5 H5U5/5 F5lN5x5.55ug5,52y[5\5:'555J55/535p5CP5ˏ5R5~%Q5Mz5??5m{5:F5D'5<5p544r/|5x#5B5=5;5j&5"5 5c5Q"5{|4J4l 5 5W5]r4%4A.5L4,5i54"59f543525445>5<45c>4l4l) 54M4J4U5E+4u4ck44#{"5434R5C 3xv4q4hp4ʃ4z4; 2S41s3lp74߹44a`A14X84d4~04uW$334)CM.)44F%44>}4kT44٨4Ϻ5`_44݈3: 4H"4J]44L5/43[44ւ44%844#4J^33E3 4g32p4^ &,2\4 ȶ4d48F48u84P3TU4ª4߳Hw g4H05졫44rNΡoB453x:LWsE1Ne3n4Mk48s43l4֪:4^pu4]433x44x4;1=43J3,P48 53#64Nݑ@씊,74 4q?ᲇҌ$2n4:W32g44s4vF4 LF4?'4Ε434\D44^4,2L P{4XɌ4A3B4crK34>4i3u44,#4d 54}4Ⱥ3s33?)4|3b84n%4q@Lv;4ȳm432-ೆo2i3^ c4w룳34 ձ4 4Hf4p4!44uV4T4Ie 4`4f#2v4O3g/4-41ijo24K"4Ŏ5)3Hn4.44Y 4ĈԳA3Jl4s*4B4033⳥{4`}zʳhY 2e3Cn.kc`A ȹ)f3iY4\4&MY^Ja=3r42坴̖SҴ[<г2Dݴ8}8S܅ҴLVӡyô#'3 [r{䩐kٳF3ۻγQ+4F32?2÷3̳+,3U4V9^ϙ1UjF" JWiSδÒK}-(G%e`|d4~ ,#FOHRsAѳ2L)δ}l9HhDp}xPN)X30BrMu<@qe6X C"8dD6wUj:sⰼ@e|B1&dD#W)4a/%ִ 3z${pN dy;״ ,z(Xpp(!2e$"D,b( :(Q/st&,Q_VH@&F0\tZVmJ]0$9LxGc.c(qІAδ ݴ\ڴMAMôPi{:C)VFs h}ȴUڲ񮢴1,Gs!"9дBBJV&xƶ>)"PSm3iܴv`)hGнq'j}XY3紤8f״3kqDYMkG^$CU ]-wJ+{pق3WKzRa}/ŴVY:).eW !9*'`RsjI:p@q&KF=)8Eȴ&'M*ZѴaS˩fٴiLִYߴpôwOps# ȴa$̴-+l1aմ-Seɳ%^2b(6dzL̳f8M:aRx0j#.{!,ģGٴ +GԴT15T;ˉF<D򴴩Ȉ˴f۴+洰Dx |@Zo>'40ʹʠᲴy3;D!?B+ɳJӴմ֪P4jijZ@4D- m"B3#ų)Dw3OR2xz,zZ8%4D.-ʹ}ixۿ`LĴqq3Q-S_pGfZƿK3{\=u|A=7Z\36ĴĴW4̪O_Z̴WkޫP2+3'44dz TqUp*?mۨ1&HƃQƔE3L3}4>3,䡻>V6v δxͳ4χg{tM7Fϴ{ճJjQ`A2j3{ry5U3i&4٠-446i4o5c 55&o65 5c+4vU5T55$5`!5N54S5$5qO5@5Ͷ4[5AB5[\5%E5]5(5mW5@r05DS5-?5YC5NJ54M5x5{5R<]5Pa>5e5dЈ5za5pbf5xs5)55<|5dF52?5u5 5/U5M5Da_5GZ5|51I5Mi5|E5ld56$5Y5B5DJ5DF,575zG5°?5>5a;'5y5F5㎋5B^5+`5S51N535W5za5Ub%5v55YA5Ѱ4[.5?tI5#5%5Î)575{4#4b5q584F5k`54S545,d>5aB5d5&65L:5DQ5D4a55]M55M} 5;5mL5N5ˌe5I5ך4{5e("5s:5!5a5`5)_5p5 )5R5P+5,85M475)4^54p55{{5i5 %5R t5F(4p5-5+ 5w5F#5K5-5ۋL5t4(z5a5355,57$5a759NS5)!5P5z-5254`S5[4^F5435<5<15t544|. 5445=5<55fR544 5 Z5:5:5e5,*y5̛i55 ׁ54 55F5@655ő5cY(5l5N`5 d5;L55>514B5G 4C5H}4F95d35mPE5%r44@55+ 5!Z5D5'5IN4:5K25l]4Z5'55Y"5eS5&5TP4̕ 53444y 4d&54$944Z5Z"4,?T43d˒ 5op4f1.5O5 4%#/545o4e'54^'5=54z4g5465d 514{4r4 4bQ45P4}244V45c$5F'54r4<5*35{4-4`5 4'h55Q4)4444?74o4j4=m߶4e,~4J&5 4/4X5?4nB4e4R3pTN4&?4q30d=4h@{40|3Z+42^-O4.34s4444W4x3fW2)V25S&4d342m3g4D4!3=24RT4s333?j3ފ4 44iй41]4(d43M04#42]4 ;4{4P5u2!4X4t3]r\3VeԆ2P^y42P/[}3[bN]?4(2k4ˣ4cz34=Us4Dy_=0LRjqDž@ޤ'3KN]$Iv>B~Pp8cmA$]pr`P՗-y+Ah1NI@S24У'(Ikv,gִ{):OJa3O%O@g9QG܄KQzusy~t(#(pK"\9雰-udD\)|թoFǵ#瑵͟/UA m~oec#DnGn!@/~h}p ._Y/듵-fW*QI$mm<(? yuX557pN)UoeahwB&cK#NQk"[;f؇Nly:!KEz`NItmNT{ش\(ɭN2)CʴOedD!Ddb= /u ˰i˴Ig<4ై 㴓Xm󴁤$f2c kߴ:i=vF{X!^3Ҵ72k3dM7ɴk4lHnk\nMʴ<^}ho. [ȴVHi H5OӵrPf2Z()JִyȴXߴGbô&!JQ #@u0T䋴7j6s?ߴSrh3=ߴǗW дq<ٴE 0Y [Q٥ⴀB-!dn:2h[>G&*=4VBִ~o}-C)06▴ĴڴL5g#5.I4.34R54VC4_"4'5\T47@43Έ484*5784 +4145Ur5/4p74y.5 G54;594z44_5'4E050%473,4[15@03f&4#Nb4w14D)4Z4=4 5\4K4)4j4(t4Z~ӣ4ui4oܵ4LB44<2 5K3i3413E4/T4s!544d3h4s3y<55x44u5Sy&5n4)4F45$44g 45B4d4$L5o5^,5V 54J-5v4v4\I744\4~k4g45OG4x 5F4x$4¿4M,334zt4-xֱT3bם4㲏34c}e44 4;h4ش4j44F744h4qY5/5"5t5OŠ4&:5f 5Xk4jF544}04=;53;R3I4ʳ~42yQ4ou4ȃ44g4\҂4ʜ4VP444 4/4/4Q} 5M44 4d4S"4T454$ 4`4"4fN4Q!4t4z4zH<5g4345F4~f4!44M/-,/4h44z.444YaM44;Pw4344@Qhi8(43T2d4y:S 4 44U4"4ƒL4y)2w58(l434u4_4=4W445$3 4|;5; 54O4Ҩ44˫4CM5|544۫4G544 40&43x4>4L4d45s4S 5o4AH5v4&444Tl4kR 5:4ƌ34t4J4Ƿ4!34r34353u3S3 ٩3<4a44o5׳4$4e44F04;3ݟ.4o94 O4VC 4^84~44zճ_0r4֍44Z2|v38p4M4?P44T54K3ہ45 h40h44e4/E=34\9 4 44433x373e4!4 D$4}4,4;4S44rG4~53:E4ǵ4q043(u3㞴lʹ?ZYԴF#Z;a"ⴥ3X:4Sǯ)yིݴGN>S nb-);4[4#_:74aFܱ δ\iq)F^14[12x3Q|x&FԴ~N"\ƫhô5ɴ\䴠ћ]ӑ $TCL.oxJ:O}L,.KT؁1wǴ´L쳔U4Ï: r|ѴltsM؁TԴ蹆kBj`X3pI4^-Vr3ms^!;$͕!{a㜴񺴲vU6)geNWS 6r- _2间.*ƸS+#t"4˴`d6紦TDyBMdٴ#>൴,߳L4 qw3SG ôͱ,l8ȴ^2L" 9W0C<߬X$rkio5;(-v+/Fa~*YO K^´qyG! &u3FQ 3Y GjqೂSTkkW0Zӳq{83XF4ܳKktRd44<hJ<&lYv\ŠXԴmPE4<4Xz24ZMu<__3r_2w4Bѳ14Y\36G1m645fi-V;DTi433β2l:4d242{32"P34eE2`@P(˳=3n\!cr47J( nĞ344Ŀd2]´KS޴>&9Yqp2at2'Ɵ$4|#cP Fr31!IHi^jIuGMJZ´p 5ڃo1aA)ղQ X3|466ųkdWN|3B^zF8}봠)U2/'3\-Դٱxteѯy3U:44?45424X0545i-5 4U49444Ӵ5~44I45}'4=4B4w4K444ؽ4)34m4z4H454 D'5s;484G5L4X4)4 5ˆ75l۲4"b+55BS5$#4&#K54 Y4;4k5>4e5 5{44zc15o"5 5]5v5@H4r45A+ 51[5 r4Z5 545V4~V}574%5X5{$4`+50-45(.5/5N755g4j4Go344)42N4B^3!52"4&5MQ54 3z44%4c4f4T4?z44W4Y_5e*4afI5S|4=4 5A5t545,T4*4;Ø3lO4!46΁4IJl4ξ1?4$4J43&ݳ.?3ة4A [(4= ?247vMF>34W36 4)72 4!^yfp۝3Z3~Ŵʾo3Ȳϳi4,3b1#֦3 Y4,ˆsTY  3#2䴸2/.330[=_(uK ]w3<u3<,4Vα;B?4%k?_/48G184B2+ѳU34 2Bֈ.4X򿷲 73 X4Qۛ4y3?33 3FB4F2J3Kc3hriZתh04e3~3 f1%'wWp4)o3G432n4'4J 43nf3g4(L34r^4_43wO44J̝3uW]1 γ?(4⨴uEF+Ęsn^4*44HCqBU@4#2[:hn\3ݴx8975**zZܲG>G4N 533"4jTó'J3j3X,糯p4u-m֮%3PZNr3.7)wo)U3]7e3~cⴂߴrۦZӴ\h]53 43~2jN` 84dJ^4bpDϳ@9S4g4D4ܓɋ4d g04@Cf Ӓy4 㴷 E4h)3T43o3ZG5;!?43V2h=44P3ĩ!tJ44Mٮ2dL3Z4S1{Q4pK4\4q_v3U2L4.3lU2 @43+NR.tg4?гN4-4R 54cj3*34B4>9}4xϕ4r3Đ4t4qV<4,4_n[3(3~3R$wk3GP0A3󋳠聴)vk4ȻS|z4M}3d4tp45Ն4z4x֨2425Sc42f3ٷ4D>=x7y{ pW-4t/V3$K3mTpO3 q2B4>9fvKǝbǴg+E3hвt5ƢR4dm H27ZDTƁ 3v ٳd34q|p4vg۲I;%4#г:-/gA22s$bIQ4ûm&Fn)̳>Z 1RP/惴b 9|2(t3\]3ޝ")Čzw2`8Ӵgٗ 13״3=B˴?55}3A4QN۴M33|31@2,v*4p55464cײO>d}4y+4hlˑM4o3Ohe3,Z40`4%4m`.4d4s2`%=4N*7g.4_4S3d}2G= 4a4A 3X);3B3#дX3 3K3 n3i<4k!YxSJd̲j3$&KX3 R3 kB3W̴:Y~p0a3YT4!4KB4"|44344x4I+bE4y4HN& 4 7۲2x3^u4T3e4"v414k423 DӲ^⍴Ka4ؒ 䳘%4F3Yә4͸4B!ز433 3{:82ƪx0M#P3T7/Th.7d0wд7(?+4ݖ4m4e4( 3̡I3J^433,(2턳B4ƨ5ARW_3s 9ɎL4rⲒh: e`u2A3&431sr-ҳT\ xIu۴Ɩ,=γǞO۳=C!YC:D4Q'-4 2ǯ4|J4SV4ճU3.r4Ϟȁ3 493dž4ð˳xu߲Z-3 쳩w"4s3>+^4̟ 2Bf."4$J43Tf3Ҳt33J5#4I3y4 z4!3 35Jr4Z54C444M4L3K84C-44 3BeI34w54 5h:54~4464432u3=5uh44J3ū3}443l4UIa4֦P43A(2ix2=Pb3Ω4[Q4mW2^C~4)>} -#4$3HН;3o`W{ M2*}5(3%o(O㻴{o״x2+#YՋl*5 )6´K3P*B)mN= 66m3Ri9 3y?kY4|4ճv.ޥӴDDO3{Fぴ4I4$Kƴዴ233F쳪g454&14d(4]d3 43zf3}4r2W47p4AD5I3Q4C4#4&1=K4^ɯ(1à4*f39q4H4,_ϳ444! 4Q4~4 3)44̙4d54W}455I+3;45w4I(4a454Շ)49)5'54ļ5ݚ3@~4;3/ 5Fy4jX4´44} 53wi2:&4F3c8ZE3q #ۗ1糛fP:4<34u.40/PR2PN443$w4د복4=W4)<.ٍaF> δ ȴ/]4k]G5Vl3ƴ͎LڪUO$ִw֞ @WѴb7oXu:3g u%Nzy ( Cs[ִ>-%WFдW(Ĵ̧6=RڴMe]?*~mnSs״<Äb[#>6'e'4l/!R۳*_w*BCt%޳U״ ެW+)k<!d۴\״䴴{ô*7AeXҴҴ] ϴjyfrcIvKմ1 |h#^d3s=3%Ӵppn3/(j-v )M{!ܴ=usB4<agu}bh:gǴ7|r> oݴh5'L˪+?d3Ĵf{Ga3H+]zXP璳ط=m4u˴n4U3_3?7@l)ɆǴXPɴp}Ivӳvb1[~׃[3؃&e{6<`830ٴZ۴u6Jއ3n *4MSå]6q3 2Rȋ3ktX9ߡ3 4C-Cμ^ ݑͳ@&;hyOɀ۳?n3`l*,H;AΛi)Ĵ]fPܲre*{3Mow2J+kl70{啕^TJ3n0[3,83ݖ4K41_5?J4KM3lޱ3ӳ/eE 4JqЖxD[4&[ f4je4+x74|/3UH4+O5|N4f:4 54-5-45m45R4J4Pt44*<4O42;#Ʊ>e4&q4q)4 44n4g4{44t45mK4W4$43#4 o-423"4i;4b4#p45,394t494 5>4۹4'453f4!4l4'|42WB15g4iKN385jE4j44aYm49(54p_4RD4d344vo3 4|jUln44⧮qwRb04*44m4 4*kR4l84qWP4 4-4l3T4va3;DzV3'_dzxF3?a4,Ƞ44yk9Ze124ل447e_r44Re414Lk4C4\4iS7 4CL43493A4}y4 42 4UN4D4K+5I4gU95&p3E4gD4C44-3nQ4=4r.`4+u4o3ߚ384r4?4_r4e4cXgp4S4D4%TTY47Vg44^y50;44O4*m4;w4Y4~z1pF4ɴ844J4+45v_4(K4F44u 5x4d485Ky4[45o:4G}4X04@!E4^4[4(5|4~a4v4Κ4 x4|4.4\ 5X454'44SB4z_5z45vA454d|434sF!4_4P\j4o4 2VN4W444yB54M4%55 4'"4484z4L4l42a4d4{43z 353344q44 5Y 5F4.}4_4S*å44!W64-/4h44 ?5(4 4d4}4@ 45̪AL44RD2Àh{2i2c4k?34"4T42G3i14]4'*j4Y4[4 4'O3'3#3U B@3(T3͸3y:4$0/.433ēZ3t;45Dzmv擃3w3u4ޥ4 j4 5!4J(5\4~5f*G4q3W4|òՂT-5T߄4э27yĈ.4Y6]x#ӳhFr 403px 4 4sSKr2B|3~瓴uyŇ#3336}E4{R| 3I3@4nP4V34l34(4b`33Zq׳\44;4*Ȏ4Œ4y&Q4Wѻ3j4,d440-2%4l& )e*GǑ3 93H42F$345d˒+uf4F 5P3J3e4 g44-Ҳ44b4 H4~B4?s4D44ޝ44h~324&c5o4:4oB43n|411h'd4r*4_m/ }4W1]4hF)fz4>)tƯԴun贩ʣ湶ֳ/N5~"X|%_2:H\ל:T2 a3L 33{42Wf-4$ʊe4{Ѫ3:4'Gg3`313L9k484Z2`43S3n*Ŵ qoڨ4Ϙ3 +Tq4@44U8},4Х4 Q43#+ 4.ϴ44{J4W_44&'4*`4v&ײb373Kk4qBq4dӣ3M46uF3iԧ4ֱ33[1!=3z4 44T3 45M3c}4L4# 4Uv4Y44k4U+4#u454J4Щ\4)2K35494J 4H6~;3x4y׻4d3=y44(4h$3y3)32D butH _ 4tP64t4253M4(4cU<44+t3z3*0444/54@4z42<4)p4̝44~)4md4{4˲aK4DV54d4;〴42ѵf4I%4X'4"ů2Pf4A43j$4r4nS1652{H4b;߳83@3334by4'4˧4T5W4$3V=4 4{HM2Bx4Vu,3#3h0U434ߣK@M^p4gU1fNX23~ƬN4g4 73.?4޴0>533 /4n3a4f"44Uy9PղڭU3m; 0<4_< ٳ˾U@FFd3_uL9Єhu92bz3a29H32HEP+3H4zݴ$3"v4>4:4oG3]T4d2L[4*k13eWV|wzdi3)k/Jgk\\ƴ+^ pp29,+%Ǒ3?444),)4Hp4>3N2G44x4HO)4%4wU"4t׳3kPj3d4R󲊴sTδq_4wz-\8!3 6BM^m|JfI4͑3tpe´ʴBʳ( ޳rHVM-Z4`m1skfԆa0 2z۳633ck2Sb|g8 bh:|3EL妴δ\OynYAA=p 21RDгKߴ7S+4oʹ#]ӴU4Ѵ:[lnWBF#,V.Q%7~Q_Ɵ$)W \l iq%g2e;GAo*T$MR7?Q۴k'Sɴ=ą9DJ~Y̴y80|P4=nuĴcG}@K5w J>͂h 3Lܴ8bP]Դs⽴^h(,3G>Уϱjݳ.w2(\0)3(dos3>,4O̓334V13Jf3D~44?4]304> ;41kﳡT3474B4ii'4S4.h4Ȝ@44+HcLr3uaR4ww4ͳp3472 [:3 4x4@+4 Pr4L 404cx4sPȟ4ɡ4q-54!Zt4444cӑ4 2e4^4 4ʋ44^4%5MY34;rB4b@3E_Т3sܴ373톑2w22dz3U432`32Yh̿3PX4T,\4T ̤3o\3ϴ~^[Kʴjb3 Jؒ 3p.W44J4,86Jؒ% 3u3(^͑3jjw˰f=5mdDn>3\qP2/3Yy󿴌W*%4ƨ4҆3g~3贷S44ٴ4cXh 3ƜW-43Ni4 i5%Xg+*"v4.4+ϨL1x$A4;\ 3T(2OH)y.M幸= S4H3QIz3\H3E3#4eHXD3n54{4ó ϴĥ 㘴r#ִIх&JDʹ6!g]3mQbܴ ɲ[-ė%ɴ~شsl1~6ƴ#)_"uĴ YO^ Yh5T#l^{D=ٴX5dX MDA'8/#'GaeCiGʉ꺴yl݌X<𗏴wDQBE!b>8V}=aҴP.$Zش !'L>{ʴT22#DO!&-)cߴ::3uSJQᠳ()>Η3Wƴ 賖ib`I3bZ3Crδ3fI荴 84U3*ڧ,a|q LHٴtc4"ʤ4P4W\n34iO84|И(mֳV)4]񄴐Cۙ47QJ>I4f434Lϳ/!4`&3SԸ2m|2yhX C%44[I2&u3H-`S 0,6F l[.$$ >MU49g&!<ʴhOشiAm|G״vŴY?K+c Θ2_rX2uq\޳\&SԴPy7ܳPq洕WNXhUv$ɅR.RB`S)5Iܴos6'8l'+>1Ǵ*#)&dGQ82o(782kb^?t 0q?Y 22)hs M}Hg^ ěYTv`j&Ⲵܴ_ l:_r3U23+zF V=3އ 4-2jmp.'$x壴״[9M $״rڴ7˴~Ǵ؇״ 6)+!% سrд3D|3"д_;2I F |V |#3|4r}4)+4@ܲ[3u'44] 44352z9$(4Nfp;3Ŵ*4b2|a״3T3L%!2s hh!x3j1h랴'C43%3-l74f&}44k444W3524oq9Ci4 A4ݥ494D4ȕ 2_2d3?4Ԉ݅7f44wOr:34&O;cLK4\2XĂZóĺkUm1H4F-34s1#34px3 1GV3l @,02x3T9Pأ=Գ^O3F.-;4$44433U3K47-4=m;1C7ʳ"2qCGq_8t<ijxF3PsRE:ƪB#S7S{'@3 4" a2*3-׳33ue3j B31ef43?=<7;j4Qh4 X3s3)L4д3Ȳ4xx2M:3nIJ-414P3434!h424!3{4v14SJ4>(F3k63n3 ks4|5gt^v՛0]3l ۴r4PGw#>4)m2Ӎ44G3441,4y4r4>4mj4*4ꂎ4b4|:"44o4O4a44v[3X4i92x34Rn4Q483G4W3b52/}4/m2+T2޳Ј2nkNJ1ݷ!43H"V3T"4T34l&4en2<4{h4s3t4U"3g4$444pa4O444_v95;4 q4*4Q4k5G4Rj5>1zHb4Vq$5&>54X4fc24*Ь4r4493?)4n5:44"5s5(4 5{45F&54\z4{X55F4$P5C(5٣44@c5)4*3AY44S44U434|43+k3\T49#3K4f44j 334(U4'3(344C43x4xn4)׸4Y430,34_ylZ~D%3Ɖ3-Vy`yዴ~s13wza53!T1eE\Z4h74볨B343t4,U=4_Ư2j4 .D4䓙4?4Y4C4PZ4b4 5ħ435p 5L434]445g535u44$4pwXpR4h74%ypǴ?4m4c3os44&15934/45M383 V4]N44J3;3D44 4 4U54T64+44*X4X32%4\4g*4 4O4ڦRޭ4]4m 212F4M4;Ű4x4{t'4z=4_Kt1J < 4ߥM`R!-4t ɠࢉ2^.]jW(bC6ո|\\333Ѵm4S_c霳v}ý]K"d⪴4tǴP _ߴ In#*8zU#iմs]@ Nlڴ=]Ѵh5ݪ3Cڴo%4b㿳0bHfD=["Y?4Q,3OM4zQ{2!3;A40DO64M4V}Rlk64fU8L4D(㳶3ϖ4H~. 3.G43 H4Ŕ4wF4f<~44f 4_!44y4*4*p 4z3a,4?4[44j4s54H5444\A3z4ϫ N4l4r5y433*ײ^574OI46v4S4!]54T5143343, 4Zj 3MR64 36ke3^ !-2E어j52eO`OD3נ*$Mr&ʹٱd=:Y2lM@Ǵ9\-Enp;1ᴭȴ̳д=״f-Bt/ŴYA~dH(𴟂Igش״c ^$D >m ENgQ0%[['CJIB 3Iȴ2ԴX)s^۴+P33Tl z^Q;b*{A-ŠY 4ٰj @34-s3ļ;VeS=4ܧ;.Fó"3"4%7443 +R0I4Ag4r3A4$2s433?Ɓ44if L!4?Q 4WˋNX4)4r334Ja 4314 4Ua5b?4t4354>#4z 4P5c55154o5#55g745Rf4l4!z4548@ 5@5p,4'Y5P 5c44=4E4ٝ4 vf4l4/4g94S4Yc3Y/4ͤ3+93Qi4jT8V433sa44+4ę4o444Vv&5~4@4®44>44Hv&3!54.45 P4́3~*4~ 454U#V5N4j/D4G=5d]m)3$c!4rO ^-.y u4H4ֳV3Ť2;~OC4ǜѴWh3x{3+3|4J6r3ġ(s474dw3Z-4Z=4}=4B4gd63q3p4B44c_n54 5nLK4On4*-4(4Q5Z3 4r4^4G4'4N4s34]a4"{|4454ù*5-o44mm*55)_5)u4v-5z.5$ȗ4&4E5z85P+5!u4445w5 I4{<5-+55s?5w5m!5V4[05ߕ4ED55535;5K5E{54o2544535A4S5~*t5%gL5=5n5 n5ؽ4d^45A&5hdQ5f54x>5H4W4fA5<47 54*45>U45Bo,5!5EX5T55si45J5O4<5iC5a*5la5155KU54./b54y55T|,5/44453ٱ`!4+u3H204(Y32ä4is4AдX+)44S[4͎سk<73쳍uQ3"|OZT7C[L4=z^1 3#2O33^=|3r$0!wz4=4wD43IJAt4<)2@(3mfဲGG1V4ٴQґj[ Nⱴh4(}ഐt{*zC!497o|Kp4:6 gUˎ'Cߴ3B4 <3Us4*4cd<4D4Z403<4{3ID*4gSD4?3գpwg3{֮4)2N"3gƳ 4۳ѳ;:F4Qm3߁ׂ:4!湳ݳ mu4v3͔4" 5ͧ4JS3B 4k51^4A44BK 3M3ʳZz/s"f9Դxij/g 2촩hnNдm[{=?tS\b Xy< {3_+ Fش%Nɼ_SrقsbNDG@˴qbm܆Aųh=0݂XxCôP4>4 ٴN1*JlPW5Ĵ>d=N1($д1/ִ@ wf& 4D–2}I,,=@-pS7% |O@R2=>_!\ 3,v4v/޴a%z[}#ŵ f洀$,'* a"Tڴ(2_ h_ mF% ޴#57+I.z{OEѴ%ЁVQCoGe?8Sy=#~ 󴖜Kvn)I)G$;G@G0qŴ DU,fBW;UJf#I~ٴ;r#'}q[δbŴqڴaUӴ)K /O@)H9Hu5/S!UTBd븼Š.N,p`N䴨E7+$;(k3J'E/Dah8i&)ߙwem~"蛾,z}O ޴ ﴤO$`K@PJO7߰U_rr_ ת?hp`h˄Y*/U^+(n-5崬_#E4&&D(+ôPWڳr }i/ +8O410:CѴC% x/'qDҴ!, >ȴHȴ<ʴ:%A!Dw#[ W<%a5gtEȴ,~8ͧQM.+`#)5 9˴3+2&ܓȣRcE,+k+sԴv$Gdϴ|ʴ}Ǵl74;:{24?8Y9X<Ҵ9I|ò,R$uPeAS?Q 1?մَʴ6kN GGeٴӧ#s޴{DR /p/9 F"&x״/2,д4f MǴBj%3~냴q 2Qge͊533eHǴֳ 1&2 aP Gɳen󀴆&v!a9#E L:Mm3) S3r^yB@׃33%4!b1l43`R4 4{4+j4#ln34Ԏx4X4Ҭ4on4z54th4"Q]4^4SF4m4M44B3 3g54g(4}4CV3*4rA4KnE94_4$3u @4;)4]T42b2@ 3>3k:2[ywG4 4F4kx4R#ݳR4h45a02t 4P44Qw3gɆ444 {z4N34\4 75/5%5Z4 P}4Z44754ff4;]4 4B4T4ᚇ44p3$4*>5\m4Ύ4344jH45U454e 5 4%43F 5!M4>:4L&5: 55 5.44*j4 5%54 54il554ejS54eX558]5ˏ5Yn5h5wW5u5_5w5k51*V5N5k5mԛ5Q\w5 /5:5a|5\5 5r555+5T5^5]~05c&5Yoo5K75>255A%95ۇ5j5NT5j5"/^5Ңb5o552Ul5"R5U5dt55#Y5;b5x5B5zI5*I5Cɏ5#q5l^5Y5w5e5X5\5&g5Ĩ5kUT5p5!lX5?5I5T,5\M5a4Le524A5 8595nL54zM5{?54`4?5Sٖ4>?49t,43%5Fw5o 54 " 5ƺ4.4r 5P 444& 5MB55#5(4Տ5~q4Dp15+44?O5Qt5M5cb4ag5Ϥ4$4e5) 5V3$"38b43Q.5@4K45J,4/<445r5[f445:4?5445T4&h4@4 4Iw4q[&5?%54 5h5*5ҹ4"5b)5g 5FY5q+(5,535E5tD55\Y5p| 5+Y5yp55 5(5E53"5 4RY5~5ZE5BG5e5j5[;50=5=p5D5γK5ZA5>5;5:53U5D5h5:@5~&5v5 5y4r55$555x5mՏ5ë5`5At5+555255W5,R5To5d5ik5_t5>^55@5F/55j55i5q55ð5Ƅ]5n5⡐555|53Is5L5t55{5Q5k_5D5C5W55s5j4%41-a4`j3_r43Oca4x)44N;4Qs444࿎G[ '!3UhmѽD}ش3H4뽟x4M 4ŪX`01UY3bb53 lz2U4_23g3f3}74e4c9%f洱 3O6z3A4ջ3AX峙뤳,4hj蔡!ǴE ;36jG4&„4[L2Ʋ'ur3/%ų2yv4l4ɜ39^4]3%4|4Q[4P4Ą4\3-4<4QT^4?93i 5sA44 454Fd 5144g52+4544244N4,:4g34&4*4i45F[4XH4%5 5x4j;4_~2 ]4t44EZ#H4d4\47>4/y44ц4144)5v44J@5V474]84;,4]4.4U4p445n|44N;4X4L_4J^b4"m?2k4R44k4 23_4%?f44$42r3rLI4ڳ4aqʳI3NM3Ԛ䆎T?2L 'ƴp1ɴ)ڴn;s AI¯ IQf@c/=&ôkd7oA#@p)~Iie!tD9Hx.%dP`:ִEu7o@WTcQ$K5*$yˑJJzMymGAD sԴ$"<\1F UZ.{B (N ش9(K߮Jms"#*& c"^v1*Q 3R(OmK`Q239cXa-ǁj[ſߴ"׿4Q3|iD3}&x9&CCh:XM.*?cl4!%#|`2ӈôSF4 Ok`8Sڢ,^G8U!8.V2ͦF`ԴppO ش78{\`w4'EAt D/<Ĵ衲44.G}3v244t*4b4q'j3m4D.8444O4=/4=#4Hw4M24xJ4.3d$555cm4Nb@4 5&82.4C34r3Ɔ4R44%g4t:4(3)bʝ2l4X4N,4G33ˍ252S 34qo*K4̼4x33B3 L5mi'4-ڣ)4{KJ=q4fr4 1y4_a|~4Pu4=[3;4{2F*!S!3⯳m۲f-k<Ĵ2ͳWk4PrH-ZZX$L!vJt~3}K;jT\$3ؖ4*ѴG4cX 4V~3c13V2#a혹3oR4U3$+43S3!3 !#4Wu;龩3 r-3ev[@`D13eo82a33,^$諿93tc\4N3_3͙4k6K5||1\4bU43ǝ434p4],5h ݳ:4E2355CQA4W14F5<40P4e4c5~4I@5 4;4`4E 4-95eG5559wv4my55{4z?4t?4e54Rw5hs[5<'P5+[4w4KX4855c5xE5|-5545.4K855fh54ВN5Q;54+5։F55>41e5I55Jϧ4Sq5N~5E5p5i$5:?5*b5\b555X55Qs5M585v,5|5q5W56i5k5+@5]rs5K5=g5yE4"544,5S5jwy5!40D/5cl5 E4 5v*5i#>5q5E5@555u5a5euT5yR5Z65Le5^Kp58j5rRf5`55b~5,e5N515%W5F5 &54!4O5{"554 }?55R4V55$754IS4Xw4V4494R5 4g36I4Z2M4;Q43Tӳ3xH4064* 44V4{%3u43̖2~4V4.4\)4.4;4eT4xٞ4~@45aW44`04_Ā3[겮mD3m4 c|4s24f844$4^4(ȋ4I4G4~4q52wL45&,4+e4_4> $5g444:!g3{3/4446 5׉4e4"4s85|-4.X435/504C4 b5/?346`4494 V5w44$Z48 5ձ4)4 ^4@~45Y4x44; 54a,4/p4%4f4( 5)5OqT4k$5 5Nw 5֑u4MC4%'55=4|~4 5ܰ4i44]4;4d4ϔ4Mٳ5h4}/E4o 5"[4p54U4k\4Y244R^4R34*34 U45/4w4&.4vm4kĭ35%d4 4443M4B4Ŝϱv54a494G44.4q4^X4144?4";3r3ʬ2@X4t3Sr4fӇ43P4A2344Nҳ{M3ZB34C>ݱm4`Wb32~g4̭4ȴ /:4ѱ,_E?2<~4|y 2 4ýɝ251@3;2%@_3Ovv36 M wLq(3ˣ34&2Hb Т*곖P#5z3D0={,I34Z34 4$i<s>425$qpD `)!7n'8v+t%XNP ގP )k)CuX+]ִٴ/߳䴫H3S2@"8YԿB*봀eI#_ǴX6F۴|Ǩ $=괐U4Դ▴~ΛA #rqdV2eS p!t5|m:یgɴQwմ9BCT1iE8ٴ|Դ W{+TYiʹ)1H%$9? q;eX{0Mś0fCpsyڴp1;O""贡tx~4KP4isj9cL4; g^q9lQ2)Us"6m״-%*(w!͆; Դ|Ϫ+ Z"`ش\+YL>38'%4]3Zi4R40Ć4ؒE2]4p4M31kj3#5t(i4=}3+a44:2DXʲ+d4}4\4~44V24i؅44Ȱ|* 4ޓ3p4u ) 4^ގ4Y4bc43a[45AP4C4,&4FE3M4K4U4w34Ƚ4d4q%1m40]d_HO27ͳ3*δ(gƴ󳇴Cl^Ӵ&*v&\GĴ tY+?"J[.v*´6?6tc O"̴rʴgճ\'p)s=X0~鴵,ᴮŷpմG洋SMFs!xfθ[;hl"T!^)eM Y3FڠȵTԹ{Z)L/jh 4E WgeM3mس۳rC46=334fe4ླྀ4}344*v4k434ߍ4¥4-4&f4zB454Ű4Z4?4v*4;4ߜ4ہ4㺑4|3 54;P525444bm465uE59}414'5Xk4&ó4E4g4T40 4J43Y`4S24x+e4Y4}5b{3.5bq 5aL3CA4%4W٦3(t4 4qć,4ͮ4dB4un524SB5lV33B4@44%733474i%3V3=߹3'YpZųkQ3y4:6Q4_4J4[<3P66cF4UCG4Cij`3qQ׳eeVŴs43*UŴ]dz <Nlp'|63A䗴#ҜgD4iZp4DZ 똳ckQon*3dd?4-дZ ԴPxmfB5dS\4y/]mԠq4kZ543=Z4k|3bG,T-d4R2:4 4i5ֳ4l4144r5_4>44P5%峛4/k4%44߹N4?c544[o4"H3e5444cA44Y153!4g65-.54GF5E44 4%43U5[4tҁ׬44\4]34@`4155q 5Ω3-/4 g4n4.4Y4Y444eM4pI4jl4'N4~4>4Lx 5!5I4* 4[4m4z_Q4cұ+{45Ͳ475l4D4i4|4f4h۱:h_4{Uı#4fH3443#o4Dz3͊|~Z"Ĵ;4/RM^Ǵ8(4u3 IL2sJ<T3%2뜬X;#r40p ҄ 㦳ִ#B$?CB;._>RJ93;?ɴˁBPγ[ڴ4}:c}ϹE ҵ׳ѯǘg9J5sOPXuѴb)-@Ѕj3=J3^3bWt4q3t\3Ĥ4UQCt4'O3DfC E3lk 4A9444n4:49ك4S#5P4H߳ 3M4B4c 4L4c94D5e4,4{4Y442>/5^5=45O4̇ƟP5749q4535%h$544-45g655e4?5og514 r4`4Ϛ4m4&5Wh4w5қ4 }4-44{5i5p4w4\q6544J4[.558575nm4j45Q15H"5&S55n.5NC5?4sp'544 5Q494XIT4'444w4L:5 5T3`45<4hT&55n44*5 4853.5p5e#J4 4lƙ430-Á2~zP4QK4~ֳb? 4|U*43ᩴ.4W4@/aJ`0<޴8u4-%R ĖQ21%6g4Ȝ ~Vxα]j[3 2@4p4 2X|ƅ74K3t޴ן'^P/+޴{Ƶ*7qPGHґ߲>s`G4Sv.N@/ϴV7b3TDaŲJ |+ݽ$)4{˳HVW5GM4VOr`?*ֳA3ZFe/9X9_\軴ʀ4z3ͲýڴɮMô14)43$ݴ߄R#4I] 3"=64>3MW7K2g<4;46{4% 4'4V)40 4e4U4ٙ4-8+4~444_284p3eQ*4#\4ijO4$3P!44! 3璳37 )/H4OV3* 43'J4444#t3x04li4 4J4;`4U4o3W4ə2mb4զ>jdx4M4ѳwqzbZq3$l>2ҋIٴU'cd6kʹY+[C9q#EjB8$G~PTp/۴˴X-_Lx-sD <,k`rj洶I״ ,K' hC=х.!olhY;GRZ۴+ <\#9I]k\ԩEԴBc+LZ ôOxôY δ'3#Kvjܴ÷ٴQ'7ڴXa陭޴#DA23ƴ덴R<鴋y%*ƴ0iĴ4=ô<5>#x3k co4D6d˦E Tx4ݼ)34]4TYW傲K!3/=Vs㡴 pШx7*L@3I~Қ]u6v߲vu28G5v}2-׳Գ=v3u4jHR5344΍b{{K3ȳ44 ̹4?4~³3d 4E3yx+84~"4H44PF |4};4CC5 z]aD1`B’43w333Pq2ϛʴ㈤ޒs̴z^l 3j2m䴱ױҴ_Yyi-*ι )RfDo]!x-`@@%F:Vxdʹ&t#0!#)cE. d5`@ômմ+}ȴJ١ bд{|:t$Ǔȴ/*$bԴ4ĴH(H _DIִ{GӴn@ q,ִR%V(+*VLX'괨/ȴwt֟1Fô}Z1Xݪ3gf,4mڹ2&bWT4yVoA3JPn3R:He϶4(3Fƴ443?5P)4c4 44p4 /4Fd4R4kh3.]344(4k4 읈4]v4,R4j4L[ 4FB4d64| 5 5*5K4=155=4l>5獃4!5 4 K59+5@45w25ܴT5&5VO5_5_5155J5D35z5,A5t5?4;4 _F5Y?5 5Zu5 65{:54(5E5V4r-5H5w5t5=5:O 5w3I45%5=545H44}4k47.5N5e'534]54VC15ɤ4@,45K!5 5IG4V&5@|4TJڨ424;4t4&{ܳۘ 4}4?N7444)44C۳G4Iу4mB4N'4ժ4UK)454 ;4Nf^4FG3Q2+(f3I4!T&o4;|3G 5l4Z4 4-ݳ443N+4C2z3,4:4264ųijp$39@43.*g_4K4-324-8485TO4454c44"4L4BH55]4K15l 5( 5|L5##5@c5$ 4iަ4~S5I5G>5 4ж5$ 5 4y1 5> 550]54544A<5p,t5\5Q545(5@:5~+5KO5]5v>545M5nE5bR5͋ 54Iv5O O5@44ea5i5|Xd555w5t5f5+Y_5 Z5_G5eO555*5+P5(5@u5^!55t65(XP5&H585 ^55^5_G5=M41{A5yI5b85<5\5XjZ5'5@57&5).5)iu5+*5&5M5 5'5AB%5%5 4L.544 5ч5~4Jq44;5546L4h4ܳ3'= 5y44*40ɇ4.4ۗ443rTdC0X43|4UO4+L4*3rc3Y334.n2z:4̧3'^`37ʅ46U4lI2yC454h4b?4N4a31>4u7$43p2N4+D4)3L`ۙ234ɳ3B`/ϳ)x421d4h.֯343riV44w ;3$:7M֪3o 4#4.P6>4j13~D3˧3q3f2)FS4s3ge04~4zH3[}44v44 549 4TI47 t3&5<;4K!4OH4f4&5!4444JX5h83R5444GY4544F35T4I4z835545?5 G44Ø$5+C5nV4Q5E5(4Z4~44 4OF5!4 55T5u&5ns5R5{44)5[5 5[D$5B4& 5k44 4-X>45644Nb44}445'5xsH&4C4]+4-S65#s44494ي4b43WS4aZ2Iy4_4n 3ɞrm31d3TzZ>q4sc};J*sRQS]дC3ôf:`6NǴ ôI-1s*l6RWb5;1! ͳE[2G3$ŴJ43DajZexݦ3Z;ɫ2}3ó定3?l˳4 VdzZݖɫ343 j u2ܳC5@$%ϲ}93 3^Z3% 5it@3T4 Jt4B64eaô?3gV3`42$404e.4+t4$4]4#~>31'I4,V34~N2/3ᘴۗ5Z*h¤24;W{wl1Ǵ#_ヴkTڳ{#I*^´ ´4!ϟ崂A+;ݴR.`L3$V%'EC@38D}h/Ѳ1:LM9W5o(7lV6dnMVbN,Cꊵ^Qj:y MmDS}2W@ꑵ\_"]w5x`8GlYx~|;%h3<, Qh,z]Yr+PRqM#BMʹc=0'J cH/ĴqR3{H =ƴXF HhpzVڳ깴=U/a%$ 䴭Eٴc`Ró.ԃ WǴ8„Ŵ6peQ1CyE{=6R'mX3\ܴwzJ 4q{-[+Ly~^4"Ŵk~ˌVdI43xܳ~}4!8. 471qIC)^743{4T48'43*3D4-4`4${4㷬3]27#%*444WJ!T39K3);K3/30j3gnsl8N2,0b4z/]ôGװ*~괮 ѴiOɈshjhv_!)붜󱎴QJ.b 6y#{3H%δ ڴ⡴rp3*9AG+ش j%ZӴD(3848J/4ۼvO3K3Ѣl3C;4mA4aq3k54r3C3\%3a` 33>m4V{M4`~4(W4=x˲?B3$32v3,443:d?83ǭ ls243\P44GF3T,Pt14[6,3X%[4383wc4N37v3V?b4Z0ȶiy054B3Tp4=҃4u3n2{α4+7K4tk2P4444H]3>c4 4ڙ4J4\*5348ʒ4$J&4x$?484h64%2g4w3>464i53s4'f4^4e4N_4P54d34Q߾4w4ˋz5;'43!3$3^q4,%3454)3s3z\4+B4]>4jDZ $4>N24d4:R˳R3>BFJ[Qh3Z6493%4ZO4wͳEY3}`4@AhS3r'B4>%Z]&4Hׄ+(1Ѳ=aC2ܴI)dGKx764jȳ+ƳL[4״?w8оsnII;⺳353߳334x6a3 4V3Ԁ3 4y4S|4P 4M*O4J44zn4~4 4\z_4;74B532f$4߳qc44γ"4n4$4944B34b4G44X4,?5+5 4H3SB4K4w#15NW"5f44z45l474H=G%44 j4g&85^U5 4o44^1$4trR4<$54 4J35/545I 5~4 5 4?v4F35L5[[4^45l75 5 85 5;4E85 5G42Z4_45HН4{4 4۵44x6 5&5Ѧ4 4Z 5R5q4 535ö5fD5b5F4 %3_5NR3 #4TD55X55;2g4Q474ɖ4p4>m4344[2rİ}4#zg4n4s4ǧڱTb4-3s¬gӳQϒ3(35vH ,3f2;c12 WoY4J)44C4N$? J34D'L}xztdzAZ\Z״/ Mh`a˴h (ZA>>{i״m̂:| ݴJdI<3f״헎7gʴ}Ȁ;/G3=?2S32 L:N [wZ3'447 Kz4 4"44w.4{3ۏ4F 5v3q4~4G 447Q44)4R=4r4 5I4+4ʂ5ˣ5u4+5A94q4L5MS4/6`H4:54R 5A654G45K5?52A5!5A 5 tH5t5+4L;4244 5CF574444n4"45S4.m4e324\4n55y5 5L`4]54rY4o 4y-4X23E4M}4tm^y3N4k4o4 04At#4* 7ŧ23h,4ײ 44zZ4~ 2w84*X33^˺4X4e3 C34s?434v3K<̠4 o3-34s304H4+4`|3A̷44y3w4"r{4:4:&4a}ah4GYз3+3 @4B~IJ4-$4*mP%H43h\<4RO3#ّY!R>ϳ| ӳyôB43yK+Y33D(yi)4H  4e24Ǒ32E444\4E044gd3 4Ċab4N53â4ā4g534]4,4044ݯ41V23D}31i443]44y1 45F<4j4~aB24&)4ߒ4y4iI4֩4b4M%4&v 3?54#47-4Gq4qZٳXEl482ӲV3k4p/4Ʊ46h4Ks 4^5{4hz3P)~W3744Bk4Ukn4<3}4TX 4]4#4=lY24 j_+I2q W4 %ӳ(%o<2zB.M,-,!^P3\xs2cMY%15XԴb/@`HF3E!дR7@!ƴv͉$3,4!W&1UsGu I{ H?( δ}?U9 5fC5XU5 4&54eA5kz4zQZ5/5s435%Y*4454w5@5s4*!4

4y364³z2=%^3ie[2Xcծ-K>,E4Lf4& :nWlܗ3~8ڳ3,EP]$^ŴqNq峴XҎ´{*3פI"n"0M,<ô%cִ eQ?8;22ÅUvi˴a6X´ȆLRR״ DNAg&3wY5U2I3u0x$d@u3Т#:rڳ/%QYdEC-[Ҵm'rեr#<̴eL<{WGaTJ񓴢E0U(e$_,43>574&4W5K1q4l4334D44v<4A4V4g4v4l3Ȟ3 e4m33c,4r44z 4a|V3j2PW494!]5}44k4a4Gi431u46'5t45&54&524a 44LY4X3'4-C44\4XL4w54@.4zr4v4?#4394XQ44ꄓ4˶Z4a543Ƴd$/(445 y4(B4z3K\3',32g4~F4uق 43>P43M3l3334@4`4]4 V343|ͳPD?4_4m3)ӫ2TP4Ɔ=aafT R^˴#%iW4Wϴz8 40?+q˴7]ڴ:c1^ yٴ_8^![Q~;4aɴz4״+[Yr 2E}Wڴ7X3,nyE䳠3BZK0q^` ȴh= >T(>]+4=Ѵ154pl Ƴd<+DE4~Tt$+4i`3[33FP;-4 .33s34V4355v$5f46gb4qh5G44Q54?u4:,44uQ5#45;4O4P4:48$5&54+5ƺ5455N5oq5i4 55LB?5z-5;4R4}4"15544A404Ev44^4H4x%5555544 4Iz4h5\54473'.y45q444333d6+3c34c߷3i2ظ3o3[4g4iu4eSl4cǶ>9L3z4y4Pmٳu4Z02xۀY:74഍4拖-d3l ٣x3V| Gi33*4z43D3V4ԑ#x3d4K5٨4⿀34+l4BG]4.4)}3U-4h4 4"OQ44,4ƧU445-D5X 4,44K4Gl4W2'5EZ44sq4U҈41 b4)4243\3b4_4\`_4zv4s46Gb4d4ԏ3e 44 3r&43"m35"rȦ4Qu޳T&14tF ;a W4_`4ZL31)F🳗4Z,icu0`0L@(`= uH3n c^'{N(oP?ڳky>C=c '-شAgJy[io@N6@>?2`(jozuBj4pacgC. '#!e#0H;1ⴷkM{|5tѴR"hk&^{^ v%]F}Ŵjb4 _ Qu{d7Ka4A'54B 5j4Q5Š495vPD5F1444x3T4,4o484Ba43c5z4'b 5U44|A554m(4b4A44.rv5L=5n TG5.\5c5a0444W4!5K 4h5s454g2-4Z4ԭ4427!4ً4x03I\44J45U4Yu32b4L)4!Ռ23dg[2+2J4Q0,ʹ;C_y03\48u3 46괣n'4zogY>dUA_32 մ4!f:n򪲴Cx a H ȴLc6D"Yd!ڡvشu}ڴvϧ]^P@VɞT檴Hl2=!}|"4؀Ƴd4t3E}jˆzx}vO'3o"21|ӴB뷴;2=1ꈂ5_~F/'2E=Q1'4 2k 43?^W3$hw9v34eೇ4 N34J%4?4聃44M46[ɧ4y4w5X4q5~4 X`4(F4k55Y4i5U4>065-4574#5o^5\504Ug 54j405 5D54`w4)c4 594tr4;,56&5,5"oD5(,5.*5Pq4 I50~5t[5p5vl55C4! Z5_>l4I4oI3`5I|5e4Ki4pr4D444+4 4 54s[4F 4Z!4G4Z<4@4~1 34Ƨ ۉ4,353 3\`:4.4=(_4˰Y3`3򡹲8:483Ѳٓ3A*F22󚠴 <LU猴as(gr0,ųEu^W/&x 9O㴛Q' 곋Vڲh_ʴag#DՕ 6۴"ϳz;R0ܴ"hĴfʴ0\7.!Ef0@%ae Lh6b-(tضS鴊̴l.G3oT'?#` Ĵy?xjK-3VMA462B 4ᡆ33,H5Nj4("PQ4U4bB4m343;4S4*cȳLL23f43p3&;B4&4- =4r4{4`q34E4`4C%y4(4R473ZB3L4_4sD2Ԭ4&45,4u3[58W4c~4L0493:4kk(5 C429H5h43а=54V4I384%44?45 =5:xdD44 374 4" 4i3X4O"0go"r'L3³ljD9qd`\/*U \ڴ}ɴe/д;rd8b+F>{QĴi)2.0,ovDTL;TJZBHۇ-(..'*ŗb#el-n5I 4N 5od4F44FH54 Ӗ4=4P4u 5]15^K5W(955."5B75*B5@4`(4靌5DQ)5ID5!5b5 ~5i45545&4.45c44D+5$4]u5m/4<4J5E5$F5-R05595 5T44M!52_54 !5b4o4v2׊P33I3K[444A0V4-4>424xY4O]5-4>j4U33,4_u404Z 4?@k40u4YC3,ޣ!{b̴WJc-O봙ŽwR{Ǵ"NeM*?rztִ +Sgȴ~մyNFᴇB !ب}| , Rr "״܁I̵ УN=j:"8߾;-6@3rߴȴѴ@Bzyĭڳ$\k:间Q\cx3ᴭ4+洟imNa}L[c 4T3Ү43˗2#سC$3rP 3{=8ƽ(21!3?ki/FA484Uq4Nk4Sn5444x4n4];55 5q)4C.4E554(5ġ4ɡ4 5?54VT4Q:5" 5RZ+5s$485B4$5a`4O44>85eB4*V3 .52+75434 4O4v4YA4`3!5g4'4ZC~4L\444vf4@N4$3/ 43E'nwk3A2,J4Vke*,r324{y `Ѵ7TpMⳇLfUixh*^]=dz]鴇/rDtzڴ ѴҴ%nĴtV"82 `hϴV:YS´,:z-Yڳk!{=P7R|݊ܪֲ4ˑ#%H8z2yڴ)LXhROUO8ݛa"GæSٗ:*.*Ho>δEش%#Şp m)-X{[3ݽTf%{2*4zw:444xI21P4b H33gw4q4ܴʈ402v4M3E?4̫4yX44bo4e2ؘ4 m5i4t43gx"3Ë333 S15 /4`RZn4=515hp|4=45@r4⴯4i進$Y4Fu4w:3yS43zz(E*344sմF43fQ4V2rY4X4b4w8os4p34\403as4494%12V4F4p3d33FϳM04QH3=, 3рW3 4k8M+4 3mlL4a}g1m4Q4Kβ,!jMTz>YR[4OvjY琴_~1ih"״no`Eco۴ZM총{δڗ2gӚǴ],3̖|qִ╴0M!xִr޳zgߴty-mBX״]0ꮭ sq%´v'˴y鲳u ?qO"q0t8ݎb6a˔uW╴!P4IEJ牴!+A,|g)?^X浲3& 뭴jXI ŀ0sʴA,w;[+!O{332P4,4ۖ3۟g43S4&3U[25:4o4LZ2xK3j#2l4>ĭ4$T4Z2ȅ4m44@E4F/4)P34̮93w}Jm4[w5`34DZ3]w4)4x5`3S+34cr4pX2#`414:4c3ͳ2pS4Ǫ4[4ہ4D64(4:4-c3q4&3`]gz-g3 41σJ4(pE41ó4 354o73544%]*44@_ 4,yZ33J4 0c$4:Z^3NB1|096Ø4 44FN,IJEo ٴnJ%@f37y24ׇ և4CDԚ>$P3Db]!gMOGh 1tVѥb1j{cJ{* } ivD7sʹ!V8 +˴E"I3xq*"4G3o2j40M4m\2 ;34g4#4U3B3D*=3zuČ3 ePC4X ָ4X4y4RYA4)3wS}뤇473xU4 3¡4n3< 54c5`Η4 5?#4V3Z%5U5z4A5,5zs24 5-j4F5ܳ3444%c5{:505]N5Q95*B55@55Bg51@4'Ek5˿4R25.5,85j.55`5&5b5x5&55J5h:4f8'55 Z5)t65W<4M4.45(D5&&4!-5s4M4(n5BC5R u544C 5 51 4_x554~75Ɇ44g4[44 ֡34y~4 334|@4ó8m4aλ3k24K}:f8gd43RԴA1>. EƬ&CS]AѴS}ʴ4TMԒFô#wE~eTF{Jִ)'B {Yڗn4I텴qb13NwӖRA,@% ԴOѲbܳL7 \;RN9:3Ͳ\_P4>3@R 4љ3+?f46 4ӊ5`4̏4A4u5B-59T4,%544(54mP%5L 55f55+=5%_5%5J57v4iO5M54cP5v.544?5Vt5-4&5&55:Q5='#54;{5o&5p8*5 E5`4+@5S]4}MT5?5OX5mq5O5m4gI4§4ɜ4N5!5Z5C55R4=o4'P5xV5)4/-46 5ؐ25S2 4KĘ4J43347h-4:c33+;+K3۵44@<1B`>j1Nߴiشqϑa=}jd&ƺbiprV2I-B%3]F d*U{F!HPhٴ<{&~^δX疴,E[d247̴B5.443pX3J=3b64N +$|4]g~d4f咲ѳ 3t걪#?1Q3384E4{]ղ?6z4m3UT4׉3:q34N45q4ٶ455З45u0#54f44h%-555x]54Ƅ4x524/5=^5u&5 54/-5D5zh25qY5q{w5454!{5~54R5m5f5|5$\5{65q?A595Wf5)5V4-51I$5t24y 4\h44!5r4}64E5;4E|3V374%42fO4 5 4 5½35D4L4#4֞3i{4Vdzn43%4(3-$y4F3mCAS4  F4)fW4Mj3 Tմ3 4ǴKLƳ9k Tmm ôb.DƳ³$zʴmm 6/R S_;+貉 C%״QjJ9d72؛f+yMaִ58X` ٴaxz|XkY+5 O0QT4uED;3ZS.s5*evZDѴQLd߀۴fߙ.mj)X9#Va]9QЩ%-3:^WóQI.43 PK4Ħ4 44j3'a(P?4-?4K7֘4Z3EIJ3D43 4 v4q44Px4q4322`424}+4a4x&4Vd4744n4W\2 4E4^4x)33yK3941 44,|}42X45u4o43/3#=c,@R5ć4S4R4ф4StoZu(ͳde7óX4w'y*!!UK$LyHe_`@ quk^?T zh3[д6v1L괒癴 0uw]ܴVɴB ̵޴fx ܑ[̩:LG촨Ĵ$ :{UA^rS[G2&^qKMR˴Hh:]M`*_4J>Ƀ.uqߴ!Y-ڹ@}u u۴Rܐe5g3驏哀"qδcNŴe汴_^-ղUR3{jAҗ373kM괊 8n锴%2$.%ٖ\o>Mb4'u.¦4ͮHTZq3 Մ3'="Yy*4f2c);Έ484gaϳY 4-X^4W:<4,4&3/14f#Y4L74Ax4o}4p4}4&4K4Br4%m4R^4.474[4R4f44SR<4ֹ443?4d712 4ʱi4oR4H4a*K42_1C44^93sͳm4!hd$~3_3ë[c@˳fOIrn43 z2~2u_o54J@1%43 ݥ2|?t3R.43aJY:*"#Ȩ峒B3Fډ2ץI3kkѲ.zө$dh 'ִ{2/^4)P% .ی%3ôxYd?;"^*IE ݴc˴e5-& ˦3$Rupؒ Se,zv;&1'~AA3Դ@tƴj˷гy=4mts4f5F5G44i4A3S2o|m 4s4/4!i4_44m0q4ʶ3Yr5t4ͪ452sC3'_44w4߻4H=5e5@R5=5+5̯J55};5g4#(5\H5/,5Z4lj54 OT5@5J5N4H5M h5S4-5g5k.5"4;5z7!5Y545V 54顰35N44Ɏ4Pv5O55EN 5v%5OF4+s5xu5F5=4?X<5Z{556C5ʟ&5pC5G5:5\5[B5[;5zg5|44f#55 `56xF55TJ4 '95B4$3t41= 534b 5"44jfg4)5]44`C4(AP3h34Q3y44/;4W$5#:4xa4;2n2Y۰m̲_L4b43A3b4G4E3}Rij3(udl44+3vQ;3Y1m؄3ze~Iዴ"b!W-Dm5S<3kUL##JZ=;!CLĴJOd´&DX}۴btbڴ.;0G{P(F6S74urX]-3ŴL.sph~"31 ܺ&}౴_γj*9v4̂4U3a?d ]J+H³3mB3QW4T13-4gW46 4OҮ45 D29z23պY092g]K40׃8t4NO2Pd J3%-}q4KO 峑HXyA5_44\43s3M4l44r44b^4-5p54wE5 MS55zC55F54 X4d5>L4E*5 M5'45a5h6K5Gn4 585c5'5X95/)5Q15aA[54455?(5Dz85 S5G5^5cO5B4V/5r3q5_]5Q5Q495C5l^ 5Vr5(44` 5D4SU56'54P.54v5-$H5^55 5D4#d4Vu4$4o44y^4h4744/Χ4v83T{3o24 'w4Ɛ4o}43b ЯyX&34$4u4DSݧÀ4I4o 404j/44:ԗ*4lO4]4933l4^5?4īϳ^4F4q23 _zAU4/h󔿴0Y V3(>m3 xO2lȺ05,1z)12'T͚ΝepN3u --q8԰NP23)2o4h=#N oK#j;2W4E0IQ42l馴64zuD4鵳*3ga2+o 4.3gG4U\q ofѳK$T374EN2044#e3d832ƴ$ hkٲi_CMЄ]4уr4b\tZﴦȳ3AJ%~%_Pîp3cwд3XA"T p货!Ӵw1 D״f2"3\J /5+ QS+44,h}bЍ@-3N3j3%u|3Di38r4RcnA {X+aȳҞ4IZ33@[L-1 3_i\25X cktȳ*4-?7̳ c UnN<KN!w楴mPd@|Z wuGoMqb ƣUʹIMnڹ2ֱ{unF=È ;OQ,v92K4ҰδN,vkVL-Ĵ"C^Ve1'3gA4I۳B$2L= 4U71 %sxԴsִ~ua(,2\F{4F|ϳ?u)e&̦;3v3^bV#q4 ԘpdZO;JrF"-'uﳩYִ|V 4/0uq44B3{*Dr\)e3u5<σ峮]44$35/3313WX2"4.3x4h4/ #W4׶Tsц44l{Zȼ4В3%4x4u4Wj>ůc43cQ}3]~4bm0X14TBT3k45됴231r㴼jӴ|(5شLﴡ I5Е-c"G貐("i)ٴzf[L~M`^4+:W˳5$ز>4qkƶ-s nqi5HygTJF93t\~jܴsڴɳ$ &0Z3E+T[J3zEZR*'374Y=j,F=ewSrB z36ʴVdʹ7rt(C;㹴iQ3[شڴ,}7\ߴP `>#D3>) Rm#44nZ67Ռ3T7_ 1I4ogH37 4:HgZ4J4-44|Pu2^4+c4|41e4uO20&B>PX44z 13: ٴ^rĴkz4<`}ng&_?2XI?+j[q;0&<{XkϴH32r3ճK1ģ>nAQ#Q, s)=4|[1 V ꌳ3Ѩ쌴R 4ڳ&۴9 ۱4m2IJn3&/GN3VS3:L3}4Z)4>3pZNm243x 4o!UV4I7`>m8A24#{-N80ȁ]MP4s\3|QV#s޲ycl205}\}2#g9N3}3%4tz`4_3(z4[4Т43N31 445س444/3'4;3`>4D!|#4ӌ4wM4@f̴/>YB4]1x&3њ4侀,3Ytp4v1>!44⥣4`튴j {4`f4QQ%13IO4r^7%ܳ3i@H%b6r=d#$3&BP4篴1I3^c\F74Oгƴ3Ŵl}w<eҴິHT82IXشʴX!MγJMML (PġJH 4{w$ͳ0㴫JNҳó~xٶ+<_BIm2r{ഫeQTP}\6prF#c}=GZǴҲSܴ "ȴDݐ'A <]oiഈG< ĸ,QϴQ9EkᷴBôdJesʴq@TĴEa[ _lD jԴ :J 괗i[r܁H%sH ey6qJ+ qG켴?4`4=>&W˴E{ 6ݴݮ(O ^U:ִMDl7Rt44Cez/6;#ob 8~A0靉K^kWt3e󪉳3!4h'miIDF ^45Cr$&XQG_׳>(D@zl;,f3cE2 Գ0GAX5il0!V\8^!T4h|4PќJsԳ44R1bisԴbpSʳ4B(״\034F3~4T4-KM3_4a 43%3]j 47 5Jìx0< 4 C鳧ᄡ4ʘ8kI+3bz3t'x3n>3ATW&3rl%m[ ;hHQ8`3 tE2~4S״v3QC گ3hI^F2 ypc_F"3b^{RR 4#33n&I4)_ } 413"LdzeƲS24̕40bŕjA3lJ. /m2_4 4 F34"Ї4׶%1w34E/4Rb4h44W^5n4x744^54~ҹ34<3g542*4A5<5䖋4O5H3g5.4J4L75ө2c4448CB}4Z2"3 4E4a3]5k~4/%4hQ94$޸31T4~44g7^4՛˲ɫ4o43!C4U 3g=%4Y2co4A4e&3Mh[3kݴU54l3I\:34G1V (3u4 4ts3ݳ>40H4O4PZ4qS%G4ڐ4= 4+%4n324m3ҵOe4 I4Wʼ334Shg VC !WAL?%53po<3L<<K)*ӴLmw7 t`ij?\73 C4 (`m>ijؼմ`r2GZOϳ4`)M^2\qdIǴ3 (;Q2B413 53ݴh <6x4{%44Z蹴4j~ɳk3t4 ~4I &33"UD24b4K5D4~c43f4ұ C414.b4S3|훱D44.%h4C3oU4ep4B%=4Z4Z ;4Idzslq4| 40BZ4LlΙ4O4׳H4')4Ƅ43,5KH4? 45=*44ly4!O44m4r4B3U4PJ4~41z3 4Q4974X43D4f4+3(i4445m4Ϡ49Q44Q4z5LL444k4SӾ34J3Ln3ݾ3KQPm=34dʀ4WdTFRf,?TF3¡4=Z3 hZók1(˴ YQOh03>2bȿOX\94.RJ~Q۴0bw׳N8A1*0CIn ‡3d" (D;9SSK $y}ʹ qj 8WABO ; ')̘=@,~r032ulT`L41(*P<3<.n&34ڎ|G*%QMA 4k(A\u1N3F^;J2/꿈>4 4ٲ bh,3 K*qij3@2c54 A>&˿45jXk2{4J4 435ӳF4Y34u3k4=ܟ4_Q!c#4'26زb@S6;3zZԴ)2'/ٴݴVW4eM24:[j2Mⳕ쳐& 3N@J~.ܴ[5r2H<'k>ɴp~![DHB=/]:3HFGŴ;x;aWlӴ4سCl%c(||ɒ(ʹ0^Q[t8L__[*c`!8E/;40%rũJ`8 ƅĠ4^贺犴?ɂ|-L :9#)ByD$$cC+mݢ"V3~3x [԰}HY, 늴^ 3DVUմ[gu⴮AGS)d XA*0#괴+/wFM3Y ΅+]Xƭ-.2Cf@,43^L44_f8 @44*4EI 5GG5N4ip/4!5 5N44ߵ45$ 5y4c55e4Q5>5+4^3W*4K4uڲ4+3\M4-H4Ĭ4?4 44E44he4#P4X)3iV42[4Ý444{214mz.4pë373m745^94I4̩34S\4Rl22(ӎ49M$Z423ݙ2_35&4"4z4c5/4|4$4i4TAʱ@4 ` N4 D4X4!G3R14,43 rl4}' r }R13d2evGwz-Ekzf94>K3%Y(KœdִT_ swO($j߳4B/Ԕ13i;[ Z2QO'sy]Wa3i;2I4}=3J42*3 41(=37D'1a3I3:"d-}N3(3hp1ڳeK443a02= Ƴ&!Zf3j2f4W.1A|Gqpm5޵45L2P>4у4$44ij"X4R49C55]4595@л45A5J5C5S$5C&5J%55x"555p5 [5b+5o25khG5JR5UC5oc5ǚ*5-5*4I5}<5 554355_eA594I4j4W4$544Ԩ5]4Z4_4 @5,5$44]5K"(5֝5+5Oq51 5?4dn4:5KP$5q4$]?4 5}C)54썶4ّ4 y5 5_4(4tY4f3Jr4Gr4 4B43! 5 3oB454b?:4k408,4>4ی31nv04 V3N>3a44%4y4P84Gv3i4/ 3H-3hJ'$r3`BB&Tﳄ]dHa'=3͠2)3.9^e۴34Ul~6nz@7ww'4ߧ/h3h4%4:3"5b 4;b41bތ84:fE54p2C4-zΥ2GQ44 4o3H4#O44r4GP4Y5q/45D4:#4p4"/5tqH44m44:5H3q5kn4F5G4޾5j4h54j#5955R'U5a4 5P4A5%4m54 L5 5C5L=h5A5ش5堕5b5S 5 5>5/5 5 5=w5p55O@55T]5m5s5ߍ55ޚ5"5Β5j5G5Fx5Y5B5R5ս5=o5~`5ٌ=5Pi\54ws524@!5g4_5>-5a/5 j5 55 ?>5j857554t5U5$494qB5y4Q25iJ44lp4"?4r4s4\4z24,B 4W5q4QBr:4Y3W3M5ʳIX@w04yqQ1p)|34G4SSN\r4P44g"4г4]Bi_3wk 4X\4Ph4\4L^3WuBeEV_4^X {h4143_b4eh3$W1bh~j3&3 ڳ}+Y3lW3?(2Υ4&:ތ9(+{A43K&4 C4 4ȇ3-ygp*>.3342%uBa3EĜ1Qೲ3r343 14nHS424T3;4"i/X4F22;3:B4"h 3&h4kI{4md4 D73>+4b4nI4 2ei5r$4'45u4a@44(4G4F4$3 043^1J24v 3r4xG 4˽3uY3щ443x24燙2~4dc4M43$e4N443t4S'3(33R`3' t43]S4 j4,36u4#^3৺433`I4n?&2Kj4or3k`4'x4 G 3~*4C33?b".3sg+ {[80~Jњz볕K.δ ˴"2rbo>qlln]1f243bp z*@= 4)^=ͳxPBL+ϫ懚ⴰs$_.aΫwH3:$#WPo=A$%M س6gH<$0zàVfγՎ 3޳yG䶴 ?0@$ٔCn3 2okSݴ ÿFh/S oM5?Sl"K`R}NP:{ܳvْ(k؈M45W@nٴ]ix'"ײC2?3l(g3so.Qm'+'69H/,ϳѴ},ٴ ʴљճ-|h+r ,Դdey&ےT1´ǴƩN3#ͳR ܴF}#4|2g봍4K4O\4;14c{4GB2E`%3Jg4ʑ43ü+ԴW =:=w=+Ѵ&X2@+;3`= HtXzk90-73VAGlEњ봝 V#t UjHF4<);I4۴eaŴь,[ EݴlM4ڴ̡Њ7Y((q3N?VJ'o93;FO=3T ܴ`Сf< ]ڴt%D(-Դ*峿҉i1^Q!cytôMr/jКڲ◃ մ򩨳`y\C4ϴp0eͳ<°3 =]s3tʴk6,|[~P2/<2 0 ò4sRY46A']4i/3+t=xƴc_]3iOCL4'4=+ 4߉44ՠ0,_Z4".4T4Ds2r3X4+4a3aI4-`4F3F4_4_44ҵ@e4j5n4&4 5uYO4ر}4!P4+X&3\x34۷4a]183B.m04frZ{ 33i3>H2'=*Z~t`Q2}#3 3*@:+\Hi}L5gxl^OUU4R5]%4rhB43 ˲?Z/4`c4Ѧֲo}4Q3Vl1|3n$4 T,42U;ȓwĵ4 >3wU1~d:=3"꘴JQu孳M3%3N\2Vݛ 3 <3;O1@ha2/ B4Čp,gw'4hƴ-a3lx43v=e04T3쳓4"U4AJ447H4MI45e_44~o4c4r44D֯@O8L 44HF4j!ƀδe~0~4>`4g3᫴*`D4d txa4²14e1r"4s4+_Kt4Dj4s4.Ћ4ܹ` v1bN2 )3 S eH4A3!o/4 2}奴]4Z^T2Ed.L3bU[4ȁZv32i]m63Љ4ӳy4m4ҹ4#4u2;B԰E3.44'5#4624%J4t[)4껑44T2P4`437Ł43y3@?G44+^4i{Sг!43vڳ?R3437s 54$4AH4< 4Ţn4W4X4 4m!345$5yaI35w494k4CT4_Ѡ4v4>*4.n4$U3C(4I3423S4,$494p=3 373N 3ɏ41;&J4^ӳ^?<AmRS1\3?34D4+4+4441"_W 5m44J3߳4rW4u`423~R3; 49c4+4243Bpi4ɔ4e3]z64>P37gVBd_B2#3;4n1^93ڳ%;̱ .93%F}Qk3ej 4D3Z4*33źB4A4ۖ4FU38g31F4ز4h4*4w3( 44.͟3˺U4)FL595iNò44jq3)3%s&4[4FIvy4CEBN%4Vp(4y4{4OP 4bK"s$ 5444j44ښ\243l44c4648l4e4Z153"Ud+"['@I4 DIȴB_$4=4V" \1T Ǵ΅rm<4Wč"~k3Kr cq4SzAo5'޳jLAy 4ms4"! T3+4)y*6P36{*#Rʴ%2=e[#SL.~:eM~Q Mr³1nִ5SW!X2f>ʳԳȇ3E 4ս0 'VGaµ'@#G3.c1wHll놢25WeP3w4_CI6+ p/2_`c Ren,ѳ?83렂&۠g(3@=1 X!GT 2Gd3Z~4?iU3Up4^m4?xZ3l³wMٳwn4%54PsBT͏ڹW342_<04 (44QX%33d);3K4U2I !Kc^2?FY43͂W 3Tz4%")}353o&r3`3V'!444a1>KNy4~)!,Ay2wT3bKp Ž=+˴L02vB%ٴ3]G2M k}c徳)YF>"3ʹ4F3p[4d~4.&3ӊ2S` 3 4342O3y _3$4t7945kv3z33c~4{39&3~3y4X (4qR84`19edz3s3C4AwK44F,=S4 45Ys32׳!~ٖ44撛eP4")1w4yP4hl4W4+3ƒ43(4N,4k4q82#4@4pv#4483r3ӑ4ұzb2?4oɎ3̳͆󷴠KtfQ4$<Α w3L[P3(1hiS3?@4sPβVMnP3 73 '$3}ťl44`4MÜ^2$T4Ȁ4ʎ^Oa3b4hV|ϙn/3Lֳk44[ 5%^H332 G44/4bU3vZ4F3; 3d4c['üyEw;Y1ϕ=,# lx4!%V241:444744[4|X44D454!23֝4d4H24M4`4]z2h44~<4)4|4٢442484- 545e4 4U4`<3 4S4@42L,474 4ڃ3p5*4D4&u44C>4484- 5ˊ4ۇ3?=5P4M4T.]"2_444 44h 3OW4&j4&3G˳f453*3,`2ZҮ43vJ'D$43.4K3^䔳( 2AS} 4w벶p4M-o3&_)X&ʘ_gÀxE䎴 ޚ aEwvK8=/˴>)ųXa۴4&8s"[[R|nߴչE2@&|.פ3 3V1"*{մ´Y ONѳ#ײdʹV>(>2#{ 3Ue2qִq23rF ؁AL4r3=4_+xU2(ldS4޴_=/lꦴ&uE.-CC C,ٸ_fĴ{Sig,W71wOf4d7 g(|:63_*&,3>׳v~5V=bi3/2tN4kRw4=0 4&4Yu4 5*5 5|341L4 54~4`44L4C3SȐ44=V5q_44T45lZ 54#4185v4e]J5<5_j565׳4D4=4 %4͍h4j84b4D5i4全4f4e44JtQ4+4D454E4?_4#425|4&4u534@5 464t.5 5T443ǿ3Yϋ425L%2j2442e4L545-4֕>4 ⼳}h4D4fO4'3Wـ5rB4o-4u44H_O:4 4ɛ 3o4i.3 1?%߅4\4,*3H%1 W2^43l4G3#4P83*7~%N 9i4Z3W,4q\ ;5:3u303P` '734!47V!2C 4_42³40J4#v3 44kn0; 42.44ʘ33J 3h4LKe2qc f4s44󻣳ljS4]34 44E43,$2$MO4,7N344usS4Q4}4֩3L"54*4X(3/U4c 53N3 4>4N4n3P4u.4184)4c)4x/Y2k464rS:44Ҵ f3dx34bWd4=46B493o3΁442Y4&Wx433G346l4\4h=4_4w4^e4F4c5K5@İp3W!4}4sJ3.422 :4 H4}=4:24T%433A4l3%44r4H٣3򧿳 4۴_1& NH4Ke3\3KhPxf 4] 3rϴX³1̳5 ꓴWz"7'ôә(*?3Hv˴wa26 6hE봥I}䜴9 pބԴ\;Es'G Iܴd=heN&4"5 p4"AP4Xm{3cc3ű2 3X>m4 Tx35?44ҝ4' 40o>4&5zt3\$44.=̱2I44 83n3H3*84QY4{ 6 q`W^4Ca<ՠ?y'[o>Y2d)Xi+2Y Xӱw5 s1ߤ3g3N63{ôA13,48ǴEٴJ `X]dz#SiRklƴʴ4XӴ$+w%a _ִG$ށh=0]uPP WX|dC 1 Ei6'\0X+P <4hʴ/)l!WjA /ɴ H׫nݴ=̴` v?|-"S gcʹ3r6b8Y+ /3jP#vǴ6޴Ld~崒ȠBMq,0FGjZ#SM > 0#2V8>^$?vS07ʓ޴qwC`Ҵ`3Xo ^Q5ٳ@Bm<6_X/ݴM3K}cZ9 Rf2̳H|(gs9Ŵ"ɴ.."3d۴Y,ടzd}p㑴*&a!_%*Jq^$ Z %ʹX ƴ ȴ EP΃S+"2#Q#N3yY괨~OBOhR}Khl2J=>SeZ˴aFI^ɴ "%;t -6 >4őO0 Ŵq Ȓnj3F崺۳v&_ϴ9Tʴa5 +X3<Է03촆U+ԴY!䴅aKKϴV猴?ݲU1:314׳00Jε^ 3X2eϳ{b(4~'7ew3y& s߳&k>3 >ױt [3&35O2T˸4p/c4˺43rC44s 4u&43" 5 Ù4I%434\2`4t\4 Y35b~4@ A4<(40= 584p4m4I474Γ4734`g3Ţ4ek=a4F455(4(X_42J4_ u+4蹳@}m4]2i4Y3?3ߤ 3}H4N4 4rûZ:03w46T4dMƲ3|C_D3ؐN D"g3ijn'34d1`@3rR43[@3)% 4I:材 4x64.(3 3x +4ए4Q4Ʋ3F34Fx4*:4/44f4{e4\3e.4(n3峘63#s!fs34x7334n> 4h4X=%H<4{W34`3D|Pp3 4r4}[C&414 ք4 4*F3aO4g3J2,4޺4W4b4a4NW2u537%5h5j 5v44$5J4>5G3r*5"5;4]3k>4c:4/5l!4)ۨ4?4l5it5)5(^4H 4U4I4V'44ZMh4o5fP4;q444r4u0554oK4M545 45Tw3ט4$5X4h5%4Ց554w4 '5~Q5=5rK5z5^P5{M'5')5nP55_5Ǒ444f> 5T.54jM455454t5U4G54N4!54߮4X4 I5C5. 254{e5v4405c5s5/]5/ 5p454'5t] 5|54nK5a4!54T4S,58 5&IQ<4t4844鈣4ލ45eQ4e4OL4r44вaD 퐪4R4[4%Ϗ4?445HTZ4144~4̊4(14EU4C۹4W0&=54*5g4?u4Z4f4444؟34h)4P4u?J|h4x4&5`:4r4o443^4c4pM45r3O4 ϒ4?A4 4sC5{404Ro43334SiS4^]4RU׳WM5%c)}4M.&2n3x$/5$3 KG@E4 ^WSovkE4365y& ̳-n5W3=z3O4P&3ί3;ꥳ4F942I44t4c*v.3x4U33i,saʲx)3)_O3;j4}`4Zٳ34+eݳ q4@Hf43,4>=4>^Ѭ3) 4Μ4U43Cϰ44"94j=4@m`4Z=(4̄3щ3 3q u4Y444x4/4.H54!5o42Km4fȑ4q34Wa4(a4A4a4'ٳ4E14H-5-5P42}4ӕU4@45\4434f#5, 591t`3O4%ga4S2X$&4s4 4lF4َ544 5Ȉ449Y5(4:5Q555$4c4\Z5jf 5q5t41Ԃ44Ҽ.5 5|4뤛4'5c5a4u444*4H5 0r5( 5Y45tP4t555955 5;d54| 5 4.3G5'504[55[4Oh5=|4/#X{44K"!>>W3V4fW3Q2=4;4&3m 4m3 a8'4E: 3ִo4Hԥp<}3H|33+p5OY41 434.45V,g[4l4%31437{444Ng0V4-4h4-3844ο3~5*4GԳ,36SX4N)34-4辳wl3ڐг4ˀ}4]4R糉f4k4f4`j<4{4K44-͡f4 0k4gdz3kv2?~L\ѴY\|KE׳77i1I3pB1봠*:4]yH3b{u42m c4/3!3e4 @4QT0c24c4<2z_3̳ xq4Fn.s# K%w ӽYDijsv#hHPas0XY4_|,433ǂ߳ɴ<-;4e؍y7[9 q$w"2x4̨32b;֬ӴE;ߴJwe}#(36г E3e2B2b c4cys 4<7{,3c2Ki4^4&34-14f2Xx 2O02:}4%:&)s4yж12豑;G4<ⴑK 4}Fq3H3ij3v'h_ʽ#C 3K_2^l3,2.'26ۯ,bz4Q4Ak4ﶲd4볡3H34R1;?3s3Ֆ|*4y4}3swƳ>o4c!W224ӪP4,3O&T4dZ$r@$r3924U"4KQ۳S 7 -B F䏋gV44u54$b1w43`4鳳4# 4[44m24D48&3UW44R4֞423`*4e 4q3;X4y$4p^h3]/Yl#4CǠ4)3m34e3 ÿ314ɇJO|4p70&_鳿j8W@b4س~}4b3#34Z4=6j43Sz3On3-sLzD K3[ci3HغT>c4|;Z 2g[4)\aĴcc4T*ó ̳N̳w}NZiͼN.0"U^V2a 3!ɳviDꩲԶ5`)4=֭R444`\+ڴXGlOL8VwZ-YŰo 3G03ȁMnR*wA3:8ɪW&1%*3c h s>DqݳG93AO4Si2}.n3׳% 40 4읖3?P334DI4Ӕ4iP3;b)4S< f*jm%2wBǴQt/ù832F ʴdpW1yFAڳ>@3o졌4,993{<%3m44 -1%4V4 m3MQ4]Y4h4,44~^0i3A'BN4Gv4Ɏ4+)/54b{/%3^4)5 ó3 3Zz46h3\=3~D4!43>i44q!4Τ4=Z4A}EI3{r3Ŕb4n4@K2‰4h+4&ؖ5x&]^u4"4I4ܳy4ͯ3Y'544 5L44-&5444 A4$4I4,4J4]d4m4`숳l154ɿ5sO4C444mH4E#4Q(R4d4Ou4ܲ444l C3( 5443[4n4hbZ4v&4RӾ3t[424554>4[5493E4,54 5)\4J4݃&5;3 5ߕ474ø4}2544o8,54 58%5C55 4k5!55G%.5nK54=45D5" 5355ie!5,/5WS 554T242a4M#4o 4 1N34Lj3s9x4V3l%4P 54L44d3t㳪24Uz4݇>4x!4V{\083̳i(44`s.4}O33BϦXED4L33ɳ 4$V4gBײ+54Dvij{[3gR63iAf+35Q4coQ4HE1:3)|вAų̚R40G!44K4UnI*43AK4.7f4L49m49gX\~44\`x4c/ 44 F4KgME4 44;4\f4W4I33s2H5U2!44 54`|485j73ų5644aR5O5p4457n5g65o*5k5T[4r4g<5/\54[@4H5q5O04T44 A#44懲4j4d4˜4-}5554 G4I\4* 4as4/5P4$54D444Pj444,v4t46r4V4 3v5jy3a3mH3OL3Wx&;,Lb3p.J4yV՟j2RS`eEL`arc񠸳,M>4,5*3"3RE3z3+1² 2? 3˪ y94 O4،̀Me3#3~.4JE2qȄ3[IF4~4`4!6+4)e$3^4>.E|_X)4Πp˴j>״}(005UUxq8ҳ7 7LdN~2m1P轴X1\@aԴ'j`#/DGͳF*fa^*_*9J t{&&Yе+'3u^yP*ŭn64輴ka3C)bQ$4Ѻ80u߀91)N 333*^ 8;1Di3SDNIUV˴*;j߲wYX카RFMkt׳t;!34p(Ճ 3.г3mz4,ȴشI4Qq3M#೗r04-/.3­UEz2{xBe{/T鳹4fᩴ]ִOϴδy ʘK8ഓY|14XakѴ*2+3_hԾG8hmix*2FB$ִ*_ƴ?q ~ ôj ?̉@co 2ᒴ#o'ǴXK)K/:6ގ@ 0(/RON<# SSOߴ=r*|F0;p}Fv d$S=<.0 jn,.@7$+ ̴ַ΢̴Zд-om&ule_2o,"l 㝅ߴ αh&~YS훴3Nb\oN jِ+1<дo63ާs2n HI괝)״䇲F ܴ00a68Y\k۽ASѲq4HHRT 93wq:n L, G}3l.F36j#A3#5 2|A<73/ 2O35Y w0R_HD崲|3-~ԴLe6޴mo?"{ҴFͲ_D1jRbR))Bj @o4 XfUJ̳/cUG״ݴZ˴K!$] {xW -D[Z3GS1ϖ1ʴ($ڳƶ3Z̸'DRѮ״Gt:M=P٢m愴.2c<'д3k[д!3$+fF-|8m %eV!!δ!6bʜ홴'UuشW$=wִ [5)޳`m ErK c7P޴ + Ei]&Ӵ㵴@V- ,Z0δAcR%pl[FMg4lݴ㩵 Q3Z_4n8 934w3pEW4ȿ3f 퇳q406Ƚ#T]C A)E.$K:b/ ش5.]w4{3pK`P3b3uOx3S2SǴI:8+ɴSUg3N2i3=W حwZմaJr(@lݴ6#㴵L2?qG4f{9 21R 3Pʹ'rR ϳ4Դ{btQ43bSq>L`Vʹ>3R馬`6Թ4r;545M5.2;5sB5!P575\57o<5&wV5yG5T5[$5>Q5Zh5_5[[5I4O4q:5r445mh44H4_46!5&۳`445] 5l4Ȁ4q3"4gw3O4 4)4Y 54F44024744NYv4o&4*4n4EN5I4u504UB4514)4c3(4ϸٳ11'Y4]4 4x3o%x4C4.0B\zxX43}4a4:rG/4S 5_44yo+4 42u4d42`-5 M@4sC5U5VS5h.344.j,2"44no4Àòa34"4ɢ484T59L44p^4њ443Ӗ4SL434p4 4P5{ 4F448444L)5P4Mi5:44C444|4Y4q4k4-#45M4425M4a444"4Ih55p4!\4-&5W454 j43505[!54]4޿5;s55]nj5=%5_4{4R355}44335%4n5k?54kx584 55O5O4@4Y4L4 \"54t~R5+5'52< 5]5 595.,5;SA515w55Un49p/5־4ʝY5ӄ4?;#5i354/!r1,H4TԳv2ﻁ3&r04yo薴tsɴ3gQԳ<\?3[T 7+v0ެ$13r91+ 34323E4.}4׼VF8484±LWh4;45S4M<4Ò4~~4e93Bx!3]5j嫗83R3熴ȴ9j&怴_cr"/h4323hh4FY0ҳh$\xI43%57sKW])q3i[=43KXjʹAI4>ʴ𺵴TK483(Ѵ[F6{E/ P#C7 ݴE_oygI <6MشR-2?a Z;VIv?- $ҴO9 }kP%C= M[ c @$+cF_>Hʹ=U/ [NJa Hc2C/3ˉ 4001Qٳ?Գ+r234n2Ak3ԹZ(ٴMٴ24ֻXU v(h;Yo՚U)_OkݴA3x?W끴p2 賷oIh 4m"&3I4{]J4R 4蹂U2(q3445M4~ B_О3u3ҳzjB컴:2&$ʪ3-R"O #մ}3O>!DUݴpy>0]Iy3SZ'WmS´3h]ıKF2E{3Կj4s(o;I[Lղ5)oK30J%#0)qHW>8T=QֳNd.* KoS0q[ א 1S:*״o;3(S.ڍR;Y/45M35Wf3\ \4׌Oyj4`)U|; lVZx3'P3}4'F,4aH[n2tKS 333a4^%edS|#s3x32'B43,#4Cc4y<27Lt4xQ4EgU4C2,6UR=+;4Jг|Ψa Jڳ8 4Ҝp2C?;4F4P4Q4A%i3HAwW3YW4!B:4 L4b4 V4=4 ʳ34f4164Mr4dN4@e4x2K4R4Ο4ɆJ4 44U*k,.ϚN(|I0o5԰%cɴθܫ|@s1˂ ] zޭ8س$iogoHΧ d3xLA7X"αI-FZ7^q"Ҍ33Y-12%4N44f4n4_Q4:{ŦGŤ4Ć4cƴC2f;EQ*Q*{%4Oӯ32M4n}4=7t4|5F4"5Nx4SJu4£444C44255'4D5}D5"5#5Z345 5415i5;5^&5h54I5644K3_4@k)5Ÿ54Z5 654Z5NQ5304ܷ5Q543!4)4475]4;3]5s54rb2554Ϧ594&4@4l44454S]565xK5536z54\55 u4Ԛ4444I4if4]2~ 4(4) 45;44A4a3:4bhX3+L45*̅3oُ2:4`4@=(4 ug4l}4P}3C2^ʹCbᴆŃ!δ봁ڴ`;8ǼvAEc39(!,4 n`oRP&wB/:Ep2tԴGδ´Apeǃħ/)v%{J@Դ´8HrDEn<8J4тb!:Vp܍4&45߳e@p A B犴3g=ZP4dU3Υۧ_2eF14[u5244O5A4^4ŧh4(4Z)t4|4 &4'q3ہ4}S4c44J.4g4l5KIXF4[4sz4n%48o3G3U|3j%4 q4)33 4m Ej೤/~46M4g1l|4K4}S4}t64֣P&4샳3Lz4A54Җ394 4r"4+:p3:B4P4/c 4ӄ $4kU4_*4W*4+4ѐ)͵4T6'44S၏gs3.=2g/S3w 4 43&x33F3q%44x3c4mȳ353Db4<4q2e^Aj4|4B<44ÃS4434/4]~4S4$ 4u4 4:Cl4l 54,@4V4]4`Ln&443P44n42y4ti44p4E/5 544L5/4f5f>5û4 44; 5+8 5CA5c55+|454|444fK415Q454>4C¯4yy384*4j4ݳ4 435O4Q44ȝ4A4Ҋ445Q4 |4q%4/4x5e4|5G,53L4ѵG4j34E35x&4F4M42#3,4_'4\?4Pۃ3z:45~413("t&3 3‡4e3RQ2f 3P4pɺ3Z3荺 jF;2(Y4Q>|t434ܴ4pӲ\34۳^3"]RM@z23hG2:Xz33ё4+*3Ԕn\4{>Ü7RY44s#T 4˳,BNb4if2F142mw3UW:4'I4j4264@5:[jM34-4ij.4w3[_b337ᶳiה3= 3 3e}$Ժ3< X'4+ FZ4^/4#42˿ 2W43@3&3KG[4Eh3iWj'4.43viB0A37dq 4ep4_.%+ꄳ42a3LqSݐ1U}cW3Ǡ}hly4։3\y+9Tz0@t;3P>e,N^03tг0UnOk³)4.4g 4&2CV4k%#ldOJSVôk45hDܴHδ-'=:3{4ik/趲*k޴໴-Y_"6W(31yyyQ<ւ ;࡯`3=v 1Ǵ6}˙6]dܴ(۴uǝ=鴄UQZ"ѴuBô[sN4|M챩v3Kt53vִ>&p3۳D1{098,ѩ2u|4E)4(23357944`oӛ39ד3 2ƳX4ﳘ23^4J3QQ:3^A44ɲ5 34Y23&%34nk JaV> 4|3@ (4TRO2_2-3()SEvK1ŽR ] [3c3@VE ɴaC3<2,-ɴѴˬQDd3S쑴Ҵ&A HhZO3Uֳxf3~h3EN3x 9Uj43 3*4lg#Zc,Vij$vd*G3U3TUu̟)jt373좉! 3hIYqY3_H@=AYe*Bܷ Nݴ0]9^f:Df*3 %zNj 40|V1@dVAm[1Z\8Pg3N2 X괚2.M´pw鲲k4R >0">n 6Um,I Z ôQX%]A3yz 3+K>r o^0ɴ, Kѳ>ش(PF,in?3g "4^_2|Դz2&[dմg±ƴQycⳉsʳ<3a|44;MP3%Rb3|o3!|P<`F4G%4a=)3Ώye43ԳFZ 4"UNI4xP#഼/Lnr3ac&4c3G/^|`xb´<~LA*42nz9ʳ ޖJt4P3+3^{$ (2T4YH333 \`x 4Op4WI4 wI23 JPm紷434e3zԴ"-4x.$;/ٴoôW?vATӾD4^ܳk30ij'3EE`gA3%4ނ_w31H4(3 !O3v4B<4 f44;33md4\4U444 p^4p5716~4>4:4]3ᄲQ4ԦQ33I,4)pi{12 A1 Vd߰.aS3K034(i{4r4>$4"824b/4D3ڢ/3o4d3TR4,i4Q`45|4x~=%54A4}z4RR54D4e4<94%43l4C_4"`4d 4'`5ɜ4GP5T'5d4M5*5D 5Q!444Q5 45.l5}?4N+4ȳ\5hJ5&58T4R4UV5A4}~4 4Rh5V 5!54554v5'4)=4!,5W4k`4h5&54܂42s5gR84j4^4[4D454G4a"5755|46%5e?4|54J$25484ܝ 5a-4H5Z>5L|4*4U4<5 5o3g4&4T5ܣ4(5K43D4454(4(4m44d{;Z4k4^4ܺ4z93?t2fF+4n4ޱ4+~|4f'5-E4 404*5'37r4T4p44443Ԑ32G-3G4R-?3T842y#44Δ&O#42Z4FE4]4OP#[<4UjW+]4=;^44~3Sf333>4i8"285 4\3Uϱ}4P2_3%4A4س3x3q(3γ3q4)4O}ӌ3546(3l{34Fk4:3M4E4vL3jj4(~3`D3({8O31"w4J4"{4LT3Z2R4ՉfM3o,3w4-5~4c4::3] 5LDO4R4N5Q4H>5N5O4 5055555n5^L5آK5.5 5|5:;t55j5F)5c5_\5'!5}5G95W15u!5g5F56(58(5 5|4G4ӌ444554m*4Xu 4%4N444s4;x44̱444%4i4X4:4J4ϫ4]44!'44444B4fU4 4 d4V1^4K3a4Xð4$W4Ʊz 4۠1q5 G'3 4 4/32ωe42C'4R1j43_-4|1A0O3'O4u3Rt92Ǣ 66MvC|- 5"feM34-%۴ijŘ󧆴FxTl~Gƴ|;ߏAᓴ81jy㴿 a3y *4Ȱ=bʴǎ<o33,YX#ɽ?4"*h>1x 4aгsXBje=$4)=LaoS4b+3bH4V۳%{&PZC2ʺZ2V3 44 &4v!54+o4ȳ!403o 4C44>444y 4wu4=4'5ef44*4 _3ij@44*a4Xՠ4"B]45I55ŵ4j48+%4ػ43- 5'3\4Z"14l-5L44t444 4 4p3{4r"4(4Ad(< 4הr44?Re۝883 4{J4 ̺u"5@Ɨ3]o4e4mL4c4}2LȘT4b46K43&a3U1c촃Դ/u,HvIK rw%GR2:ϴ G#ЉZ꺽̕}]ԳOʹ1;4Lx ֏lnywQ! QI)KX8y?^#մ%p)0^Ĵ  ܴHr˕ 4L3'2T4's=P3'3HU04)36<.413 3ojہ[XoK7&g3Jۑ3T۠4=&Ug4[4"aHJܴ(j2#Z 4d/f z#Ĵv|Ǚƴ{t>'S!-г\ba8 B};0n{_3)&/EU(Soͳ+VF4~MĴM93i3ͼ4}쳾R4$@qZ3421\4'I4u ߸349&2m&.炴󾖴E õ8Eش߽{3ڴ;;ڴ<_cO\630ʱ :'8363K3ֳn}n H&*/32zKQ3l 33霰p4362w4.3 1v4L444W4݊4IsѰG4w/S]45V3CV4E0a444Ճ4λβrס4]43|3ֲ344Si3wk'ŲWn4Y3OL45m4K?440.4E2k3e' 4 4R11mo4433)4S4l4!X4I4!%4Ab4x5#4B 5/ȡ2x434~<4ܐV14s42&34 3e14l4;?4O4/3*4w4¡3e5}4ݴ4 4d5Ե4Ų40+5­%5@5"4a5:X4S44ϖ45-464]55#R5'5{&5&I;5U*505†4,ޣ4֮4'4fH,4?4; 5tn444;44$;E5{44$4C564!j45t45Fd4 P54;Tb5'4G>4 4V4"4-m4|;44HU4{44{ 4Af~l4gA44Jt49xw4ĺ)p4K4=4> `4F446 x4ToR-4)ճE3T4[>3^4\44"=4$94d~4Li4x5:2w4:d3[4#3IK4(46p2142RIy4R3og4Uش4VV.3n˳85g%4ϥ4ߑN24++N.46OCCZ<jM e63duruƫ4FˏF*˴-|CŴ-4~0ٴ<[s[JγPA3Bu̴z`_!4泂4!4!-υ 4CҳV]Ax43F쳗[M5#Q41C4Ap4=3jp 4Uc45p44U3Nҁ 2433 S 4L4?2!Mj3e43I܊40m?4ʹl$#ݳe2ڴ(-Hq2;3X84H?4њ4R4x 4$3%5n32l484uO4~Vh4t4e034F4P4Lk^4_394K#4˼q43;34.44L4&4[44474x544ݎ4﷐34ƣ4Q4z4Q444w443U5#4_0o494355,31=|4M6333k/?r4K4V?3by3l4qgo1A376R3@gUeR9G3Wrbn#4PڳV׺.J3P]v~u03Ή43Iȳ-37#3|cij4_kW.4۷3γtD4P:43NWU285g]Mu35V}J3 5:%4M3β^H3 }4+ٲu49*塚4W}3vMo6k3vђ2왳3&1*wC4|%i4>Cγ1P23.+靳'034IB4.&z]M3{@*v+4%3m?v4)3É3V4u_y_Ip3L3+N42Wկ3:p4>34&44544k4 4F3^ 43 434$Z4/545 ,43r"5444Z254l4F3Uu񳐽V433i#4kbw4#"34c2*i3PTL3R2UH³&&4r=&z4D3$p3C3YV4!3B23 " 43ߏp*4T$35~T4O3)2AP7\4|flL(tuvd"´N\³5zᤴдzg8+ϴEځEX˴k⡴U.;mK۴ǹ3'۳2TG4B k؟G±x3.3`ôs-D3<46 :3;:=:!4'`1=T클[DӴĴHx ,4FCO3x3q7 D34R84O49 c~a5.^4?A444h4=#3~43~2m:4$4W34f4̂BL4,$4b߳2dY9=6MF]pd=Q-m+3*Ӳb6شpC4l4#e[!4y3934:@9444@N4'C"]3À433a1202:4aA4& ೋG2:cA "Cͳ\:|俴Dδ}C`@FK1Wa ۗ 'K?A3fbLڳC]ɕ丶E:XY +n 洉b/~dE{{Le^g޴4#Ӿ!ܴ)?޴.[9ִB.wmܴZK(vഛ@(ЎJϴߝs=-3 ?%}J6f\س7Ο3ƴB .矴$V)> k]Z$jڴ4$̳}[W_~2j%;aS1  ps(Qrkj|q'Nl+KUyVO;Qؑa<:HuCϴX`<ţ-ഗ,鼛*ôz0־ E)ڴd^Գ'/Ҵ ۠yW^1GI\´:,#&*n 4{)[kȴcⴽ,3dȳm{øSôX}l\ L#/[ʣuk>3~QWkuNO)ڴ() a3T?80acJ0C.7BTmɴAk-h3tdyشUip3 5<$4+2G)0ֳ\44{3N8 B3̴t퍴9j;鋳J%}7n?!ҴʹǴs{40wƴܴTt:۳su>G lXɣ)6:!M+4AfXw ^NѴ´:K޴drFk@Anx2k4"#ִ: e;᳅ '3 _2&4)33( 3w`m)+4JH44eH3k473i44@4C2 45d3f23 fj3bmM4^3n34i2}2K/9d;@3]h r/i4!{ҿR2N3)~=*4J430 4 M3#>ـ96ˋ3\8[t4<4:Q=3IKs43%W4Bq#R_Rm3Q23V4] 44̲ 54y 3HDpp4W4nM44iW4|3! w4m543!>4x4"4! 5#2F4Q;'3? 5a4v4H545V\44$443D3[44ɲ4z;4z4[4Fn3R4W,D4Ӟ4[y 5c4g(44T߂~4ol3F34X4lh_4"5@4>3m4 5y 5Y4U 5s44$454,4_4?  5i4q4419457h 4s55l54at4=484 4m83, ,f44)C43644\5c45!43ڦ3l7494O4 T*5j44z4I54) 440Q4T3o4߼415 ;5-4з34-15*4R3 4'4{34-F-3g4r3/4K4s_4344ʆ3Q3 3v3O0瞳S;3X4"24~0}4UdP4x^q3HC4C4d\3h4P1²ΰ{43&44/'4a4 ;4ad`4*4A.4u 5ՠ3*4yob4S44g^r4{44L4A4s4Tr3& 5&4@4/_4h7أ4K|4L4B2'4*|u4 2~C4E4*54O4mO4+]4Y4k4o4t5h3M4*=15gs5֩3z4v4|3:4Y 4d4}44O444S4u44R44-o4T33S{4f446:4R5ۢ5T<355$ȓ35P5($5M4u.5 4+41Y5144=G5754nP5:4t5 4\453D4zL4cG4h4b4_404:44=55[ 5yL4{42'44~2144TT<2h¡o!2q4ك3=C4RC*17+B44iWw44Q3 4(3`>ղ4s3KԎo-4454B3`9<4F 4&Ne޳@ 4~{3wY[Ѵo0 VA3vLE2잰\O:/̴v-9R˳ -34Z:4.42C3|4# 334#ҳf4p3 $4I3533o4[~4-3,b4YP3j5]ӳqN4 3r4`h4-44h4OW3d5ٝ3{S'4K4yS3AK414c؃4445F4'4C>4;4kE1C4˵4&Pl03n44´4\46e4g˳)4D2d,zĄcR^3J443w4K394o 44!xZE4()3X2j?mdR36>/ O4 qX4y2q޴ᕸe*V3:2XԴM2tV>4eVg6ֳ/laݞ[tѧ5'ӴɿF;xJ3qc޴SEb_3MGq<#'ϴ񙘴Ҳmȅ2.V-д c3ZKSAӴ})X ,=3i[*DԦI]r %^ Zi[P#]7f^{01J@Z#+2hc˴:B)kj7-g0FgV!(IQQ,iD-m!E0.s@T6lS>ut73_c-3h[' &1r մpC봁o:̑NuUrS&*ܴ ~Z|)^1iǴKN/۴G3혳|L/'ٴ@@YN{s',㴬gBdazVك}ߴl\ãU1C=g0naD2'7!"6S"*|NF3gዴxe@,δGBsAִg0;-o.C\&b. <R t'hLд@IRN]%D M8%:ȴ=C ʹgBi>&a-cA@ְ7xFwy: ; #ŴHr\/6Ǵ6!gjP!*֤s:]wɴbj\G.IJk'䢴̴y6Bos"sY` ^ʴw-ϳ&ȑJ۴wô{҇FJҴqjδf(鴑jƴLŴNs̴t4|G ִ-뺴߆m崉Xôa{ʳ}ʹp3jӴH8}^Ĵ;ش?z E클B#xVB *1JjX[Fi#1 R*x -=Hٳ'i {*-$va Դ޴f) ^0̴zxkϵ/wU \/o^ Z?Ga=p˴/4)4@F3񝫳5<3 4G ́4H̫U4眽z~42-B4 4;33-o'Ò3-30En4d4Ac|_'jP82/ nی4ZE k{o1Pnn4t5Ƣ*c4YlK$4E*46s^nk(z4}A4G2SI4\P43a>4'?4[3'c1f724V̡4[n434=4!2$ɩ4W51422d3&4`3ΎN2874)1j40I3J{4A4R"4+"4N'K4._3Is4 5$35GC4z44@b4o55&,4SQ44i5ka4gm4B4 44i45494]4OZ 5"444NI4 5 4" k444Z4 44|Y 54 }3Xw44PY46U4R3474d45ڕ4Ϻ4*5f3_W4ˌ44^44 45N5(4(5'5A5145 5ʤ4#5.G5h@4s35?g5AH4b5<&5KL4!5x-535. 5:43]44y+5/5 54Tq5 5d5Vr55!4D5,5C/5*04:5x 5%yK5O5W4MV/5O4'5455fS54BC5W75"5 4"5Mߏ45Zib5&4B5ʈ5Iȱ4,+5#52&44 5/5M5545V$4:455q55~5r5O 5q(54+5]&565x5y!5n4 Z555F5uK5&4554"55(5Fd44R4x>4435C4Ǧ45`4V4 \$54 55|ƨ4/-5 >5R5vP44Oh$5'45-:5&4Vl4*A5156&5ZZ5G5RK5z5ߓw5/55O5W54H5?A5U5VE584H54B]_5f5"4,<5|5y54?5::444d44:35b5j%5II44$5Q-/5P4 5m5,4U44\45v54zm4i5414-4:5a B5Z5}444v*4543(5y5 554O5V4q4$4U514-3Y-5&4Q3y 5ۋ5g-5GR?5?45{Q5Ս4U4~444r 5}4 5]4z446b4T5@414Y65ê4F5S4%444w-4WY3{4pf 4Z34#`4635q44i55@435.446B4N4D4\ 644`:4{@4#-4kn,%4q 4u4a4O`3r&3#J33j[4SGȅ44}7HgQ42r4r4j3i~x4u5 "4Wd44 5-3_u3L4W83.47D4ԯ4nȳֱ3)74ŀ3px)e_4T464)Z|糠㎴~kR}G?{޳ųֶ3dP3JyӴ^@.ش)3n]F]z33*4ݴwD2)QO?10R4: 3e4ſ3B:C7oL|w3mo_b񳗠3Tcf'.rUZz4lZ3"lѴ+ܴq |5A)˴v(ȴʴ_Sbb3?.T쀴 *ߴB洯 KmٴщvJN\:#Q Ĵq-,P3=Qd>+I۴H,6\ f Ś;MFô;_n洩5AkKCôV ` Z 9x  ܴ7;˴d[p3bs,ִލ1%& \ 2d }W񴖸 BxuL' ش\aItZƴ4ം>]D .:7m ~,m"Ou4b WʹwɴR贳*4b0t!nm$@\rm S}TG%N@?Iϴ0s8^δa>JᱴŴid>,Я3-R^O4Z ;p]4Cz\74r&|e~,.]4Kl <Lg]Ѵ~? ;ı/UuI3<<$3X9!C*UGD4ra>h4*᫴<2㳩6X3w%pxҴ?!J4ߴqs3Țnq%0b4ѽhsɴI3F : ȴQгZ>#1!Ҵ)pEi.hLz(<*31c33g̱n6̉ }2O*д-.S,uGFP }ה-4x_P3ǴҴ)l2 "LE@ ԜQ3O Xukp7HcffL33A Ql3״2❴XDٴZ.tdck33y3ڛ4C 4dyK%2 \4 3Rt4JHI3-iN445/ڪDh2R 4}:0~z?!5гd2AƳ߱I֖ѳ<>2/͊3fU53/i"в1?2qVp3<9g`F3;^74wRx>v4B𯴮<944Ѳ B|4µ+4XҲ/\3K4u3 aˎ4]x4'ֳ:6ʝ 犴ʣ}r4W#3s94~D(Qș4u3m"4 3Q3=o:4,,ٕ53p|'3y4oM#4浍;[p1@x3|=4}'44433Mŕ4r3@4}\4[4a4HkT44P44)P4Ђ4oK374DV444IY4b44D4mU4O!4743mvd,P{34ˎ3s^4-48K_45341323:44>Z3"3^n4N1`4 14314T.4!3 44Yu44`3"4c4z4S4U43_4w4""4Y440D46 54 4E{4r44Q3?P314/!4 4'4 55q4h=55L444U43IC4n43LC5y4EG44a4 ټ4n=''%5+*5[44$5495uH5Y4Sc655 )5r 585oI4"5]5b4E4z4ؿ4c#5a5r"54w,543\%2|4d4 a40+4ċ43E˿48"5!A4.ϳ썻4PW544~:u4u4d|474z51495;5t4' 5~5ñP4N44H44h4J04a 5>4?4D44&5434A=;4z4 4|44{445S3@,5[V54s)4!t4hG44m[o4*444o`W4jxT4 5(>5=vz4t 4h43J4bF4)84~45hZ4^4ٟ4X:4G5s4 y4-5I4։4>/5 $4'Y4Ȼ4.4F5@45 44g4?05f4)4lv4Q4I'54 "4f5m'4D 5@4#M5444)4G4 E4p4 4c4434 3@4P4Cc3V5⭳4>4|4^!5;#45-54m$5%414K4R5h4ex45s5`W3'5;{1|484My4  5o34&45߳3.54  5J4b44Ftc4p&4v4.y3EN4\44(443w34444`-45~5, 5b:44T4Ho4=X4%4ZC40 54D 44;^44Y4E4qd44O54Dy4.44qʲ4uK4X4U44%4 4\^3#+ 54:G4N޳23a4[413h 4YY4B4443gPu434/볫44 3iq4a\3@c4C5Ub3y 3"4cղ},RF3 2V3NX O3߲W04]*:Zu S4g3,|@3P4$/M4 ]44cvszt6ֲҳ!O4#H4>35B4Si949 4=D4)3K3jj0߈L4 Lyt33{DRC˴JȌ2nʎ3R{eSϳ3?}jw SJ啴ȴdu~ܴpԳ C39ov(ױ4 M$M~۴j*>ϳ^hNG PqϴAĦ[Dr4 _ .|LϚpƳ%hU*&ڴ#yQK㴆6Fo⴦kCKAHu50ƴ-bض"&j(Iy"qlߴ\]jNRmiJS7;GRȴAO೴+-'-CtݴlLֳr>a0d5Uعt?La崝Vs1_޴#贎 %蜴{Ԝn@pߴVCHvRϴִ*Pʳ+HHbDKgs!SִC*ϴ.ܴNY^_pHڴs;Q8"ʴՏJ$arôEuc ƴىp&Pf"!Kk[S M%ͬy̴P?{J؄_%Y]ݴ޴?fi0y#,~:b3Zƍ+ln"&\ْBR'h1/) 9 7Z&i!$ Ǵ #-'{31v4R44Z<54Y441P41YI4%44c@44U 645h3^c5Q4 5554L444L44m4O7 3Y 5G459C4332,4Az-4`u4 4i20p44E4w33*4A^:4 54!C43dn4 C3%4!4[48nh43f4PC 4 k24rѳp)4;4Eڂ?94ׅl,[Ӵ-UFRDK񡴤s3|Ӡ 3鴧GR ժ&pOT4C :: ɯ.U4.h0f\E3癴P˳|l*04 ^+D62Ԁ4a41JO4ibC933z4pʄƳn59344G3Yލ4P3T 5444L423 3K34.3z,I4(41494G54L{84%ȥ45{4/4 4242U4$44ŌK4"4 44fʯ44q7444S5j4~5ć]58+564-40R555a5'5C"5i4u4v43t4p\F54*5*444wWN54]545i5ň5jQ5C5/5y4F~5Y,5:54wX5 $5" 5`65"-5~/5l4R_ 5 j5"545+55T4485e4644=v55"4Ў43+4:ݔ4P504fB4]W445`i5^3:4m44Ym4!44N44vK4q544R4y ҳ4dT44;ʳ 4^2a:4'634[=4:42{-2,h4h%EDԣ-cU2k4g`@ch3ʱ254B3%ijC4 +3;FQf4>444gbͳ4B2%44Pu493/44yI4T 5eL4(3 X1\o431}454 C3H4444:p2C4bw3i}#5frd 5%4H 4O`50444mK4+4_4/4s)p5_4A*5I4-44P344\U4-524X$5g`4H4T4rR5/45c4c+4 ѵ4 48?4C3g48|857c4_(5y34-54$44'44\5(54O4?4n4/3}5"4D4 ;4ˢ4z4Y^5G3Ӫ4XԀ4!?41c4=L3Tk>4cT44cz2 94U5453o׻j45D4U3v)3&!n (볓ĭ3^423s4B%45r4j5!]42 4Lub464)4v3`>4*3,5m4qI41445aJ4o4YC44MKV4WV3ˀ33 3&474 4Z4֭4{n~h4NFƎ4G4J״r⿴p ͞;Sih_sȴδ _1h^zG۳3 ٴ>Ř} h|d>N3uSi3(3 @t2سB@ZkXj^6&?ϴ}Jf[yCi Ҵ{"ld3fTRXܚ 4]~Kjմ촙3ڞ3Wf}@?4V40+7 4"4n 4x83J- ."4L"mRZ])G 4c7$න7~ZPNs4T)'ݳZ3MNٳƂ`[* Kʴjs<|5?H6j˴se,LZശ / x:'W¦3ǴӴ5P474\-=52(C54o48D5Ϣ44]4ղ4*5܇ 44X)44'45[4E244c^404v5054 4}3Yp44g=5]44D~4^3;3s 5I454x4Y44` 5!2h >5^444 50Q5r4)45;j;4W4^45% 454k4,5\4;54z 54Of\34Y4S454^4jś4f|4=4+q34483=k4t4tG4E%4c4鰳4֞*5J54z4!5q4w44%4&"5a4O^45p4P'55'5̶4oC5B4\+44x4!ޟ4A 5:@>4/b4|4B4|"452*2344u 5a4b2 45.4J 5Rx34 3|5W4$4o44,"5զ4&484:v44յ4ʟ3#|74ݐ4*N4Oc4ڿ4 34H4Vg34wR4E^4Gpx4A2H5ҕ344dw4a*3 4 4b4Tل4N4_k4c!%3|5!4NS4,4m3 4M3%8ɯ3>ӴGѳE,ޕbɲr%Fv6&9x.GѴa%܀ݴ]秴W۴"` u'\wYeexFXfQ !wg! 1WzoP/x^=: (c t#ߴ?5c|@/:Ŵ۴XT3Y5`δ9눴Ǐ/ɺ8^`c񁧴`ڴ +Ϯ.ƫlGy[V⥴윝jX´~Ӱ -Z+^=-|;봱 ͽo=7ܤ@Ӧ 8W0FTʹMW :!)2Nʴȴx  G 2uYڴ &𜂴i\ǴRO-t%9 D}´R_ִcYbXX!״-KN괏մ"du)6#ʹ> p$f/ڴ9u|ƴhl{@aWܳyq_.IaewH2'´6viXoU[ ,Lgش6ϴį|@ ӴcӴ3l_"p7޴ 2Zdz:!;2$ l0r4v}Q,T/K fX4Ӵ$2OسOO_QmдnI[Uu1TkW4A]Ŵ򴗁δ ˴+o>Ӵ'LôlݴγG,&c峮#PtAqO}z=󲒳0!4ʆ| 2k3˴mA4c`3-jݴX?3C/YG1Sg441$̥:N14>414|R3ưb2Xe3ȿ3+384p4xG4A*'z4W4թ33 2#4!2344i<4~T4$[444Lݳ4{4 P134!`:4: үh34%4Go4x3ѥ4#}33 43 33I;4A4DH賉?a|)40V4FIW3#B{4 3eî3^443+Q"383WU43)?U!KA:#t3|k;4 k84`F@&[_v3־J4+MY3`, 3̳ؤ4.wM34>&4d47Q06A4aof2p@z3s,$4NQ='3#'4ӥ4Dh3!34ڀ4s3c4.4x23E`4D4x3S5C)5 494;h45q4hg8434V3s4Kr+4CD 544` 55ۗ4$!44s 4\n45g%5:3m%5c4h5/475434q54Q5Q5v544Ȣ)454t54C5֡4M0444<44pE34{W4e.5C4) 5}c4474$55S 4z4"4ы4#k5c4z/56=4a434.}Y2Wy4I5B4@g1@S3-5*)4jB3 4 23>O4Eia494p@4ՠ1w_t4Mn4y%n4􇬴Zʎ4l\4j.4oj3'x4X34سC2)KuƳv r(U_]|ukb\4a-1463W4 44 33~O3z154]B4…3a_32433 *V˳`@4 E3Qv|n3m15'⪴y $ 5eh̳}4 Am482?4&548O44d4q224G 4\4̛5*5x4 wJ456,4<5 l3P4˾4Ǡ|4j4S'4 -5$4| 5G4kG4w:4* 4+5_4 4T4U44mV4K4R494L44j44s;4&E44"4j߱%3z 5434q8Ƴ 2ԑ124n4.G3l4l484Oų_Eu4;C4394\3JY49͓45m3<4`4b%4iR75-45s5`44P4u߆44. yM4444404Ơ4+^4i$Q3324J4BV(44j/4i`4}43BJv591{z0F4KFw3k33 \3U=63ΥΗ3߹%/pi4>M&#Gi43:4R44E[44 4&x4Ӻl_J414\!3h3 3%4ZlbZ94'83$lW^:"^33ճTҲ33ųh3XA3h>44a4p4`4O44z 4˳44M4U@Z4G*4F$t2݅4924d4ل44ZF4x0=4g4T434U4(4n4X{4I`54z4k[4AO542544Ԍ44W5z4DC545]a 5m42595[r5SB5$ 55T_5?5$X5 4c4X>5x`44ϙ4m4ؙ4%'4)w4Ȝ4"[4w:44B3:34}4%$5=@45Ʀ55;54r\4NJ"5m!4<5wb^4%4% 34@;44I4o,+4c*4'4 %4в4S3T4"4)5-8b4s4Z2f4k45#4aST7<5^-4VgȎ 44 3l@3{O̳U4n P4J4c4سӽpӐ4Q 3B9H3:SG{3:|4ҋO4TH4Z> 7y2 `3'2d4324*4 #d2D>Ĭ3lⴊ,nR^Ӳ3F`C)}4o0pI4ҭ473 X` 4 5X74,_4 845aG4Gq3B4%43WA45D4_»3r^g5j5s;3ݎ4+<3A4pw3ץ4WQ4 3e45%T4z42~44ԕs44f]4b4!&4DY3unh34ݔ4HA4t 4044V4>44԰4"9434eu4&34`)4S44u 4k4 5w5ʇ4`55E4_45*5X44HB4'5 4f35 |384c.63oh3J404!F4OE3"EGt44v444s6u357u243)gAV2b5b&3G{4 !P]23+54ΟGXش>.<*޴R"O1H:0[ѴBU{خ%1|{f(;س]F匴j tL&T3{G3F4I~4q@?`NXD*4hw; -4Ѵ4(pC}8Fo޴$!eATօ(4 Dn5| ʠ o4Sϐq(鳹ex&dbPhnٳ{}23t§4pk$>v2%G4d(= \ ]WaqѳnK泗B_ AӨ3yZԳЍ9Kw3 4jδ̿a37b6Cóa19._ ie{:ij;M +=ESڼ*tQL:FGTKȴ)rR;gyvg7}i43,5X_ior,;v4}_szxGGXCTlE-mI7Dn)hQ Դ\EC=w)Udn 5q| boܨ}7YEmQ~88z%Hs㎵$O23DcNhvNbb0%EKpah=JkЎճT25*ۇ@] &\"]<12ၴIܴeqɐ3O04(Y4'γI4 314*26?+p\4O4J44h4Sz(4 3b3I3u44!W4zY4&,%3 4 '3N23V54_ cM444@4Bp4 5V!4u3д3ae39V4g449&54y4C35u>5{415b551[4/555''4c4jr_5H55՚5+ 54P4"444 5D4B5c5:555v4F>/5(4,5Ł#4 4|.4ss345i4:4}5N5. 4@444jA:5.4C5 X5@4͜&585575wi 5 $54,5:4 5755 :5c5ҡ5`!]5rUF5(Uu545`r4ΐf54QR57=555:95Z5qXY5NJ54`4?4']:5b0545 4`5*n5ͪ5*5Q5"5%,5}55#5=.5wg5"5'5I/5--D55in85e5u}-54b5۩ 5e~956 5F5$/5E,55uZB5g=5\44htI51}54Y4eK54@5ja5Q5k854!E5{5N5y54~R5z5a?05{>S5ȍe5PJ5KZ5A.5Gnt5^n\5:55vJO5a 5<-35ˏ5'Vo5zU54J5e;5=55 j5{!5Ebt5n-5j55g@5ry5e]5q b5}#5c05c5 ~b5Z=5ϻT5I5f5 5vv5m\5^i5CU5Ɏ5[B5'5 Xz535mY5#5i5ǂ555l525U55{5yOz5q5/v5 -L5\Z5}5"5S5,5Os5U5m5 45 5cP5 !5z55w55z5f5/y55ؘ5؄55ڪ5W5556355iF5+Z55_&55I\55kn5_5m*k5S55^~553F5Ξ5N}52|555 5)Z5j5?r55w5akv5Pb\5A5j552W5VP55"ծ5?S%5u5Yz5;f55j5B|5C5*;5:5n;5u?5|5_A5ƒ5T`L5c5OA5%\5[5TV5y5p5)\*504zk5584*%5d5[Z5*5555-05/5s Y5W5- %5S5!5O 5)5 \5Y55Q)5%4='55~ 5)44 444z?5`<5W5K<5s25&4UDT5O5԰4!54 65(^4A75)5ZYO5\=)5K0552@5!5k5xQ5A5g5rm5 O5@tN5;551V5U?E5i5M5NS5 5..5a5m5̟g5?59w54%D5+5g5ˊ5+L5,554g4E2c5Wk4@5$V4˫44^5o4&564X4>4A{4A5-5ag5eO4VA5_55oG155,&5z5D5J45g5c5"3514]5 5k564x355տ45\5u5,M.5w 5V4&4V4>_415Ai5L45~4-4e*4̜,54&i454eJ&4~ 4<5L+50s40n44,3,40m4lH5 U4C513A4L|43ܱ_4;#3̺42g4 *3Q3S 2[ 59/44o40]¹42h4*495:%ٷ 4嘳K*3R&&4<3^4J31|nd3v4OL3`]3S3)&4Ve3F}4iQ"4Y3^:2Ŵi4c9̯d3}~GbLX3Sq">4lJ_W4eq?ߐ49 3354ZK3;r:O)C4ޗ3rd] ó4d)4 4ϳF{@305w8b4m4]38 3;kBB+29uOL4X*48 4%4}14:34,ӳI7c#3V3{22!V3BaX4no4ϮՓ373}\cFu@E2dz35f7H"4m X12%C4wFOݳ?} 4r6Ed;~{Ek3ӕ߳$Lճ/'ҳ*UbdŴ(㴳1S1o3mPִ׳ӴVx?޴۴ʹQ0M1叴UgݴDMkNq;H P Jb z-[kCCfӫ&FRô :;9` KD!"#Z6[YD:]PH%⁵{&<%hAxWY=!]?Jl +BnJkD5D}}"Q`f50Ǥy6oJDrB#nck_7d>R_e0 Y#wZfT@16HڄuS^wOVk~gPX(G*i ?][5+: L{gGq 5ʹYp\K6s!S_ G&W+'΀RY) Tѳȴx޴4M y=r@&%Z𳈤I24ղ2]?4&g7t2E#o&JPI&%k'434F434 =3i4D4)BW R_x)!##3N3W9혚i4,3)o43 4-2q2 2)5943421!4,\5x4Ϋ4/4]3h 5>u4m4e3NB5EF4س ?4 =:'44$5kr44354y"4H2I43$g&44%3&464g4lA2X5,D4UP4L尽 \4XOI$3&m4E3K24R2>44s4/4|41 N4_354)١z45v{4=454v4` 5p5v4q><4|3J4iI64l4ܳso)414q4h#qʩ3t)54aZˆ34 64-k4&3rb4o5/4044ۥ4^4嫩4O35g 5^44 4/4>55l;5a3585#5"5CH5Le4=R5o4w?5=54S5 5O4߬4k05'54U4=B5 >#5>5"4镒4j9C5%544U5hE5ސ4 5O514n@D5P4z4Q55F5C>O5?~.5I5P5-=5J5d4l465m8[5iwM5*{E58`4?:555054vC5%4J4y75*5]54C45x 5/55?5dk4V4d5164#5fDE5 5w 5FW5/y%5WBc58'4Z 5N45x85S5B55%5{e5516g5575 4| 5Us44@j5-5/58 59D515;5Ÿ4, 4Ƌ5A5mV5YO45Y44Y*'5j4}m54S 5w#595S!n5o!5C48:55V4 5AP5 5T5^95[n5"44QK(5埖4:4E3 ^R4I542y4O*5q)555l 5 5.5mO5S75L45eZ5;5`iF5"4Z>5BN5u"5U 5S5l55_i546/5%44 5#4U 5{:5Be5T5 5S505 5uO5]5Y4j_4p464445.5O446 4SY44_4 5wM5w_ (5IK54-754W55!l5lȰ4P5v,5P451S4>5S45c595T53D5B4B5t(4h[q4 #5׬4q5855g4s5,15't5Un4K4U*5X-53<44 <4~8@o4l,5-$5(5c515 5@5(.4<55(5s4X>54Q4~b45444:51 5x/4P44G3z0q44O] &j<4 ˰<94{3 -E44\C4>S4h 44~2rh*zŵ4DGm|)z43а4Ŏ3y3u䲯°W4L3TL0w'^`4EvV4C;4!43\64^:jyc4Qӳ4C4W k4P={2鳛cT/94iؙNɽ23=m=-H3Mm433uR2 _4E40rM|3H4 3qa34*2;:4H{e-3ƽ3?2(b4Hd3SY3%e% a4b Dݪ:23s[ʹܕFkEx݁kƊĊ@ bLjB3󫟴kϴq+m 1m򫴥3$4jU3e3{ZFi츴ộC 8c) 13JŴ?=녩2hx6紗nb<ڴ4lg4}  7DPpᑭMdeh#ﴳ+EIzL[;D;TڴW%~|sTC2E۴ٴ+ü([4ڳ)sô?)&}B4R2F}@"r~&ڳL䴆^۴ij]ŚInӴb!3[Ĵ:C :F*8n~ɴ'2-ai"Gx޵3l4f8$3$gߜ4 γž44D44f4nM4ChBD5x3p@l4^p4ʳ3K4S[4M44%4s/+2)"5ý33Ȼ4%}UL4$(31ԏ۳ (4g4VNc3:3}23@xz41443&4dC4<3U5':3w ,u4894y4v4$4[޲rS4c4_7U24H4 5ؚG4|q434Ԩ>y1!ȼ1-3~2 2+p@ʳ؞3y+ c2-364wh3[J3=SX4 aG3I4x;O4d袴9E3'޲$C -11WM23jq4YpT&vk4r4-4t3g4Ik0NG3P3N3DV3O4*K3 b4M484H4w4e3fR4Lb4e4mp4K35~30,4fG3R3[4ɏ\`3s_Ų%/ٳ|o94Բ+h36]3$n44 4g304 }"434+v| i)d`4s&4ȖySjW4gh M9##30d%0UTD #gH`/ ٴe) 6\ ^ !ȴԴ+'*|27&O}*f^nWӴ^#?eΠp2U'(nA%"2"73`&W9!SB!ENCr3`ʏI2@\~ŴȺ,4m7R˴}ykclVg:QmџGX㳵3fB3y@dB=3n442o37uc3a4C4S^36VR@(4 3-˰"4!4\3XK**3^4[l62A3S`3s`4ډ3yIz2{_TʯMh'ǴhX(Ϻ-4ZP1^شs洓+:9d9fu8R7Cƴс>f{S'd5Xдqv ԰5-2Ə%ɴU땴u4[uEt!ct=_벴o!r稴X@S!ͳ2|Kte rKٲ"(%$Z7]44룲~{D-4v 4vJѲ:2485N4(z^4144z44˘4 Dj4A3C4K#45&%!4\틴GX34<24G2s7'4 c4J;bV82Ն3lV34 i4עA!I3o43F4 i3Pt3Ӏ4 }*4E4KH3U242m3'3K3z4c4!3N3e״֜2F73ja4F3ӌ_3Q4 33Sj4.4C484T4&M4͛P4 3/l!rp .3ǘuj/5ٴɍѳn4R3`RSBs\峕)޳F7! g 3ݥĈ20;r+M{ݓ$42@ 2XG44}`4糋+c4;1{(4Խ4JFI)5j84ђw3A3۟۽3a 4L5~4.q4,4Ր3>?44ѽh4J3]g34b]4XE4,]2c3J3ڱeڌ3414L3|H4943W4@;3"445N44MK42ŭ44+1405>-5UW5e5༞4ST54(4i|55P 5Y5K5%45\05d5Ӣ4D5 4aM54"552(5 5HA55x55z95S5645 5Z5+%5J5:F4 /5 5e@5 35!5?5; 54hY4;P5o5O64 d54et4J=5v,57475d48y4ע4"464ò4jo4M4*5&Z557{5zP5ȑ4mo4>55?=5ٛ4c4#4344GB154I$315 #4D4+4J3u!4+4]y>4`44#4i`S5P1Ԝ4*4 ^(5A4(w4#4 4f482k434W,45 4$C4c4:4m3md 44ה4:[4G4QF5520B-54|44c4@5>4\5Gg4-154f434dֹ4 `4t44Z4g4gI5F4ТS5ƅ41A4@5\'4ǘ 5ґ_4 5T4p-4OM4.4H<4{%dm455.4Uu4 555Y&55p45_C4c 5PA4,5/45 4;4 5;3~54  5&i4W44484<4h43 5PO5 4k)4;5405M5`H4 h#55YA'5̣5a$5>-I4ƺ4 4ȃ5[44+4%&425dgs4d<5r3Im4B64 4Jw4XO4x x4^3 5435t&5>4b^5+C`4,5H3l44,q4w5oQ43l4^4-=464,q4k3 34}%4h4@X4)*4Rp!43/@564Z!51*3Zo3T[3 ͂334W3կڨ3dO4rc4 s44flr|4Pk|3 !3/02xU34`4f>4=2Ϡ/ى8nZ;^wg'l3GLfn#3AT2DʳZU >xPG[3nV5:4SO9/l4en]e^˴ {8ԴGL_tϴq'oѴ 1(OO2u2C2_V 4 2J 6anզ\mv) lZ3ųa>{1>yճ3veڳh43blP3ύWw2;3Ԇ2LXشHY߳3ԕ32s3d4UO3:d3C3|x2γ*/2?I4b3&|a#5F4=e4{1@Ƶ04^3^C2m%1B4W4U26P,2DдG4}/X 3\3aq54zζ3jC27<B 86=4fUഇѴDݴJG{дw8R洎޴u'nv\H))nfI:r{5ʏȴ^p` yW >p Rz= #$Ӵ_=2D)(Dj6,ߴ$մy1´\RPj$j.%촉/3!%2m´OF`Ȏ$3%g3u24%ͤ)| Ŵ-勤=*>'@-SǴ"ub+dfh15D44*s(Sfͽ(ƈ 3,Q)ɞ3b?O gOƴ.Upm/p+@)T#MfijϜڳkM)IP;7y6@laE 2~oH :޴6T̴lk%oBTaL2+A#迴0Onʹδ6 Aߠ6,=(#贫#㴖2ִK]pB =(|5ȴ&5sڳ+@ }hԄrW޴2qV ϳ̴ܺ:-4† ;l *_д$CPDD}z3)~.q\ִӨҠ"e³ɸ4'ZNvV.3=Hh3q׼k6g3r3Of#1fcEH<3t 1 5#"4f44n*3WM 3߸4n3FE~4L.m4w45b4l645Jh54;4ͬER4c4u4֦4^4o4q4ts4b2$4}O85 -4r34D3]4@¿24;֤4v4܋#41em3nJ3&۳ 4M461O3ժ4#>ر4^?3yك434I:3.44LpI4m4*S4" 4/)h4E#44%2̽3Gc 444` #4:1w42)j3>4\04L21434sa4J~h22{q4+b4>M34!Q4`[E4@y4N4pH3HFM5844XH4 3~4Q4945[P4l4Է44Ӈ4445 454X3<3xom2X394"8#4&Q4c'1 4*24b4(3B4Qɳ!5Ed44<4>45l45'4<5_354_44l2a5034O444R5I4=5'#5-$584Uy4#W5p}4܌~46\44 5 5{4Sj4\4^4:"57a4d4׭,4d55=4l4v+54!44|I45(5U4UObl55n42 54 4754v51CU4;5N4@d43zD4r@ 4͋4v4ǽ4a 3ɝU4343q4g44F4)<535Y54b5ގ4465I4_452?54 54q5)4"544145|5I 5443 4ݍ44P)4s`47GY4?4C44I3ӛ3y341g4.4 4h3_36 5Rqs4dI-3oց׷4bFݴ {2r>'_3+K3̳>p@4W5B774۬qrĴr[/pP g5'䢴-г3C tR4;j4<0<-TV9u2; 3 ,u%na4_G4W)=C`ôz]30WIp Ut𖶴+3i=7,r$MѳU)O8:ô,&K!ŃPδCX%h}:(:Ӵ0 $ /:*l,^d k,߫pT tw pд9OW/ܞ"mIW[5S+<㴏% ̴EJ 539h$D宴4'+}ٴٴ7/3nӐ1ý43ųL7Q3<] waTᔵUꪴ!⭴5~"㴲;3{7oAhѴ۔Բ1򹴘ٽxƳD)#p[nԴ叼ɋ4_β_Zo-2󇈴,̷x}9_CasӴ۴I^S3*R&3ٴԓ'۴ ?s78+G x4iƳ_24UND9K@l#9u2rKV3|NѶG_NKVf=Iy + Ǵ/$MlQP |mKl@E숴Tp c)ƀf:R[X4޴H%t-IEʴ lũL0$}K1$GY1q={{n:D.'uY[X~ b[9Cd} N̳}f"j<ϴ|Uա0W7K򴔼_^ue@ᙴHr ' DYдE<)䴚Wi:cܴ\̴KS2 ?3ӴeB3lTʴ|B3DDsa]q4v 4MM歴+P*c2=q㴼e W 3$W i3 2>43,}.444ڵ1ȃ8IuH2]}He\޴e#4w ~!4":Uд=bD 3)4*-x<kԴ@<*)´CC|#u۴ ϗuf೾Lٴ~)Uv81I~iCX AXo5y)BLum>q+2G>x†Pk*'3ZGsYɴR3G2Eg3i X2ȌFSF@7}U4մ! 3H4f<4 G- 4!F3]3G4+Mڰ.1ø4W4)1禦4 3[:l@4%lz4 _~2y4~Lx,4dX4x3RN42Ι4444;4-[4^z5/}q4-3ŋ464o5H4V"44-45.Ԉ4'n44V[4]55g4č4}?4)x$4Z?555==4)Y4}4Ɩ4'4544J5|5,Y4Ņ5$L4o.4vb5T`48r4cd5t55H<5ZPI5'5 5(5Yjx55cW41!5 5X/5]c54441G45B4L/5&C564#5z55$15Y44m675P5OA5-5P5 5v5E5'?5vS55R15^d5EH55-75!? 525#\5*N5]x'5u5v58[5{5[T!5n5R.5h /55755 "5@5,5a5vu(5N54k4v5Ee5vrN545ł5=5%5.L5K5Lx535s5|95ix554t5,s55w5+5\A5#Y5[:5*5;55575B5R!5S5T1]5oj55ǵr5%5255&5ts55_p5I5cf515e5j?E5DH5ki4y15u5{݅535Rǎ5r5G5"550k5 w5X[5nj5To55Ю5J45_)5=5M@5Z5}u5ʜ5j5b5.Č5q5=5:[5U55E-5T5L|5Kd5w`55'r545145f575q5a5,=54n5ie5!5ͪh5/55XF%5ۭ?5.54$I595_=5$565)5i(5h75M5!<5Q\5!5N545!55;515$5_&55<.N5&q51G5O5_5?5i75 5Ľ 5J5.A5YT_5 W5H54G58-55WA54>5544-5/4 4{4D4P4% 54#S5:E5`54H5œ45u5P9555W4;)5[45 45Z4V<4V54M5&d 5g 5C444d754s4H5457555l4} 55˫54Ƃ435BA44 95R640.5F(5L@5#5.5%4]k5v]445U)4T/455\`4Wi4@G45Z̀4˅w4 4b4P44 54l4_Mn4' 5ˆ4e4S4ut 4f]3.o3ɂ33۳P3-3Zn4k LL423s43 @4&44x4J42?\4WV35x*4 4z4Zi4GAB43W4B3ڳ9?4k` iN4>4D3 ִʳ:wW4~$[%̈>24jT40jWT['BLBP(3 p>`h(a\6?մ0*D|ݼ /%678¯-.۴9s#A\㴶E{Fճ> >4$3] дWCs4}e=´LT,3b?y3t=4|[q32I03B4P9Dϴ;3^] 3%i3 Ee $}<+4ee|2ƴN*-HAJ7 ` 3\Ҵ0,?i"ʞ~9ôE\#J~ ۴Yd-Zִk ;}~|ƴ=k VN c9s"N )0q%]X" 5/wF=Z-TK #҈Iuj!Y !LA8aI2-FsȄ|癵рrh,>""J̾(6^VGnr3A$TTz1 Da}OC VE#a@{@Y4NVOmJ67A6qv }*DO)_-p8e.)x )XZ>5sCnbP qmK(>-FSDMmL7nr6#N0شYm,z8W 22]Ӵh+ѴND3K\+:;\״i>ٴG /MC%@Qw㹴.>jŴUOa鿴Q64{.65xt9_X`O x9 Vc^&DŽiR;vX1}C; j `~tYW[FZ_ZmY< uRa:S\,6{ʩ6<+BZf" ko=6մN X W!]>c?<_$.h(2 2Wƴ?3& I7g{3#A4Aᴨ4N ]ôA3д$5K8@9D ?zƤ AȴB:*ԿYj6ay7wBj43S9J˴^Q3hG޴H#PS4aw 4/4RsV4aZ4:34٦438S4iQ44s3 ̒ۙ43ó|T4ގR5Q4Wۀ4No4o4448A4γ4h4 Z4 55j%5M5(4XJ4sh=5 R5x<41d555U5!51+4B5# 5Ne5r5l>5&4^4 yI52'5F4&535:.5E:444;ڑ4R5|4w444۶4\5ɣ4F44lYD554>4ON5nxH5'2:5mķ44T6:5]5HD5Qn4* 5Mr5T?G5wZ5,.5 4a[5q5}5MR5Ck5U514ՑI5(!5p35.E#59=5H4^4p )5Yױ4{N4+504V54Ž4B4(S4ӨC4u45r~354$5G4d4np4Ә4_4X]5P323Wb5Y 554O4404PN4 4@ 55!5/i5,^4U4t4a44?4 51t54P43U4_5Od4ދ45?4B44ɛ 4HV~4rI44HS34 44{54d44t 45fzg4h44!5t5_3(494455Cy45ݪ-5p]4m5X15a]4a4U5 45Y4n^49M5Yk444?4i44Hr44v4L5{4`44+4Q:4343yw544k4/˲fu4Ԃ3հV434o43ѹv4DI5rp4e304i4X4EF4$4}44rGX44L>F4 3r5Q374M3"{4w%Tp:3qA,3q943k*c4aдVS4[h4694Zن4.߳|ae2C3yo/h 5]49߫3SѳЛ(48R=4 ȱŻ^U-+4Wl4uT4ީ|n˳3d*4m՛3ﳻE.+Є2w9yl3* gx4ixx3k^/+}0J˴}vBF1848дh2/W)݉ޗ4-`t'LXEг^Y鬴8dzvy'MkH"'!æHC&cQ%xO{>y@JV?kAд,T%]/P%?sr_Feд;\{YǴ 6RfXԴ羴m܇ ^iftF7zJӴr+ɴV۴2U2c0E ?,PGHvhR;&)/ ¨G 3I7= 2;w5Sz? )E2 Nᴈ6kôKZ˴kwZ\5^.'|.MS?0 ִ I޴7/ܴ  J -P F8&(슢rZtA$KлQ}7+ޓT:JYcAŴl崲 rK 崵 ΃zLw~M1Xڴѐ/ إt۴zEðd͸1{g$\ǮfruJ:cҴ볜1ё3S0m4~2Ot;uS47j2C7k4շM4Tг92{`v ~BqJ4$ 3'13Q~Emxyn3`%lۃa4/ 7/7i6\4EV46DF4-2 hKrH떴)o?Ӵ6̳ٴJִϞlj~Xô:ʴ:ϸ#ѱ~ڵDvypc2dtTZ a2q3ױ&.33 * `Ύ3G:hp34ЍŴSL4vZдIp4+Z+493oMoZsw ,,;'|ϴOY-sLM4v3 ]K3p.!1״Ǵ 2aNI23s;3tL4q}G4ʝö2)X:k r[-9{Zj4`4^4> '3ٳ;"!4C\$뢴P-j3~xݲAw1~kD@4ꖆ2'!34P3YCؘUѷ& 4i䴄b3<#4Ȅn'4{]y035`49494K44yF4͇3`21cv%3 B2<ˑj (+ŏ ӳj~4h4ᣳT4;;)qS44 |Eo3I54&p4%ކ.44{s4n 5|4"41P4C43SqL4s4V3. o4yp44 3t=3 N.4x4R#4C3hm4q4к4v}1qxDzx ~J34%3ME W~4Ğ% 44ƹ4ۦ4zL4'4c4M45U44fX4ȅ4~354!3`ͦ94:{34zL3~o1j)1pd3g443w3:4Z3M#3v hJ4p2 sK*=4$U3}y W3 rr҆4GƴE6״j3beV3>떴z@f2Ѵ?4dXo /2u\mvnIפpm 4K8ܮ3?3[3_44Byɋ y4R]Y?ͳ4[z޳I4e~ó?4@4)$ײsʲ(C3lxƴ?4Ax>U\XJo3fkYCд}}ԴnU峚 +oij#y42v27e4*-]4C1ms鴎4($4N:Rഫ;ƴZej̿2?24Wŗa]Id3uW3 |#lvA2y74eygw;6^4vIE|,53߲3&K4,iVy2z47 <83;糰0T4fK4 s"4Hof&2#3 2ED47#4og.EgUvq{"1 w4XӀ3nvg|೫?4:yݚ=N }LNET@^F5N4Ύx3%3(4ڍ{2䅴͊3<2 )0)4ab4N2݆'&+°4tw3B3naBg@gƯ(4@%+Emi 2|ʧpZ0 *xTiowAͳ8vܪѴAx,44|pJq4?/lh3pvv.*͓%K{7!O'3ؐt}ZyȻYNd~։BOoP#L3bsu/!CĖ'z?ӴܴA r+"݁N qi< > 2 n|+Reu}F洃ٴwwvaoLl =|KCilX<|H芴 R^ʿ&ô[ڴN~[ ۊe,4 jALX-KК`"`җ'm䴑u@Q2<>S\z)(شK´ǼkJvrxiʹSشg۴4C@b^33,43O4w?-4`4cEYmY3zt22Rظ4׵4\%2137s3"+zݴ Uy@]J 3\Sӳ\}3Lj<3O4B4_΍4.30x3&3rj44P3&^4x3]d48{33n4f2d$474Z *45ci443v4骢4|4$454!444h4M4֍5F4v4?]3<-4t3{{4I4<4N4R9r3x~4g4e~433/3=3m3'%K134O4l(ge 4;ۈ4y3 d4e d1{4b4 3ѻ4Dz2^24 4 '4#4 !M5k4 3 5T24C;{49^443V4=(43qD4V=4-4s94PM4~44q?4`E4438B.3;44 4i٭4k4ೆ4Z]K44R4u4)4P4[43+5644x 5w'4k:Z45\3 5;E44i 4Z?4 44N454-44@44$4i4^3&54H5#B544,4\4 '493r454;~4o4=X5[Ա4Gk3 5,v5P 5o5 4s544}@4d4@l 5F4k/4Ҭ454l45Y42K534$4A4ˉ<44N4,4 "4wq4>G4u7 5df4I544@f4> 5b5c4㠣4/H4ub%5\H4D5n 5q{56<4j[4ea493+42454Է4 w3ثN4145׎4\1&5q4r^4Gh44j3u4Qp4fG4N4KF4^4a3ˈf4u14s5+w3 5J_Z4Z83 4H4H4445e+4B24&p4q2~:4^F34<"4c4,+{%3ʘ4wy4#ƐV4s3C5_a4kQ3Q%3%4"3T4(E24XK4 423s]4X3M4o1O4-4ԯ4 #E4z4A)444 5!Q4d4& "5mj3>#-4`95-5v 4h4J44s 5|h4$$574n4Պ445j65C@5\F35\454I4#34c4?3i4i~wf4M4a5Dr14h͇4?3x4_5{гހ4l,4͠3o 49ڽ2 544H3#5*Ƅ4T4S4qX5_4G3rF445w4A2559L5u4a5I453~4y4544&r4W5@55U2)4_45;374T4y4O Q~ٳ.+4DЌ4b4?3BU>14kE4۟'34.@%3p4Վi4@4Pq5{X4045E^}4F3Lk4444 34B43531WA44gn4:3Mh4,46x43 4uo453b4c4S4 _]4Ȝ4_4,!4e3&H¡3>U~4ҽ4FʳE,R@4}4^44 5X2سy4s ~4#{I4JP3\C~̲_ 764rPY3ї54 454S 3٥4IF3=2\4H4A̭1M464 4s:3u34<4M)ztߴVW6dôG3xM!ӴV珴%R8/qִv0W)ٴtdϴ dI{3ghp#`U3)Դ~؄u]q.*1R1[ 3δ#4vK[䱳մJZzNPF3Bڳ[TSǴƴfb񢝴wmnc+ܘ,zT2Uiׁ3"𳣴c/s@x3YFH شk.RiR}Ԅ8 㴛X;䯎*x3{s4$x˪24~4۵3P3IY4\[4j4DE3'4uκ4f3EDV2&3!d^3S K↴!1 Ɵִ/DO6鳷<74l48~42MUe>4 (42.4%u54ƻ-54@4421{4tX44: 0n4 V4H44\4W5Ge4242+534{44-5Z=oL44"4534-5y4 5`14 4/؀444QH44b4{4!"54ŗ4 4@ 5͞G5H44p75 s5#5T505dB5|.5D54ҏ5)U5E35|5/W5xn574575">5q)5_5]55#m5V4:4S5954ܥ4[5*5m65S44k43X55d!4E5S<45܊4l44,5̆54F6G5#(4Ƒ75l 5[4M5ä4C5(5Ճ"5E5Ug55Gw5)-5i5W5YP54(5a5W45 551-5g 53 5.&595G5U5L=75x-5ō5Af5î#514?5R55fGH5H 5q|=54515z5\6 5Ul'5A^45505!5@44,<5BbI5:`585BF5/AN5C65 DG5m+5L(55|54D/5ˮ5;O5.534P454Cސ42c45~4zM5E`.4Xw45c4X05T44F44 44!>o4d44ʨ4D&5(r4˖4;5k5b+55H4V455+.54~35 5п4XG2_5.5?74{43t44X3l,J44W4͙3~44zv4GTIce3.2J4 4R324vU446!35粐wq]E3G4|4NN4dd3,(>83P4&4V44Z44C3KU4=J4^߱-4g..3=E93ӅvC2j#y44NwO94~sD3]>>7 \}⩴hG3nD4KM3c,Z4q`Ϣུ%qڲ <="a:Im6|8~-[]*MO1P%[ô#R0MݴZ)tT`EG;洤ônK05Haܴ? y8!ETpϴea)#l Ѵh]'!"ܴ!&!#.)K1l~ 0?G1˨oH* eC U뇴k!-qD'B` ijV㾴+Դ))b{7\qTCwux a+hn'޴ `.|tQ|$EǴ19&b%55ǴMt@r7紖شm2pn#*s ٴ;]3T^"HfaJZ7)T6-r9'&xW޴<B4nc:Au#,hѴ#K@rôô+@UInb״ ƴ{5Ov XɴGҴ`rh>´un0eu,U.e']*G16ش 3"3˴Y<8 ׳,3RS4So9Cm|T⃖8װ.ކܳ8򻲡Z"P8!˴zJLx=4Rr3Lb4Y%2G4y βk8C*¹1[z -&iU72hഁ X0󬤴#̻{6\͑~! o 3a jU߈qxE9(pմ0GTd4@l9 O@TFzlkP%kxm2&οtv ^SPE\])s4vM L3ц4 \4q޳'#41Ss] 2;н7 >0T3 ` qj3ԣ3QUAN\pzitϳzz'CnIU4@WBg!O{"2<2WI[F޴5wX9(`⳽A@3`6"Xl4{l4e}3fI4l~3d(49R=4hg4ҲYA40(4p 447454<4a+4Yp4k>3r3:4Ly4f4=O5@R3܍44UP4_3CA3SF4)A3r)K4G{ 4^5j4w4t 444+4Tc44"@<4T2a5G4 5Δ4m 5P4%*4R(5FrV4tu44042+,4Bz4ٔ4~4I_dA5s3G4?4v'3vT464ϫ4n4Ğ445 5+5E44S4<54̃4T4ѭ44[p4T5e4HR5?W4BC4 5T&5j4%$5h4oO534A?44 44"~4J4Y4R/48M4po4P23kX44J4[󱮥 44Sv444St4e14Ƥ4w3#5044~[44*5554H453o5>4e46[45^gv4f4Lp5{4{h585E5J44J5'J55=5)E0525>5@4ꧺ4pV5\J5.5~55-5v4Z4L:5?4 44=C4L&5vU5.A25tj4`<4j4Vi44; 54eP 5U5G55L*5`j5r5`"5=Q5vu5 +5Y5K(M5w*95'(5bɅ5i5d 5O[5%5 94y5h7d5)Gb5"5HU5TK5v>D51"5FB5'5l2J40r4x4484"j41*4#"5c4a]u4I5Ŏ4[4x4eV4;(54o:4ⴎ4454d4;h5~;5355xc4U4 445=5q4p5g45*54Y5Ȏ44睷4"sE4%4X4z^[4锤4z4 V4hC45l4X34 05Ϸ4&4GYu4x2 O4;4@y44q4\0QD34:5䵀4^44J4454Loe3 w 4R4Q4]\4_4XZp3ݣ 44133_&-56l_ݍ3>e@2v3'4uQ4ScᴴHwT^w۴aɴP5_0%J1㴣zijݴjm4dش@;^N30sQI! ,t@H)3Hw3:8u˴|ܛ2]<3*2M4rKO4AF3s6ڳ!57ֳ޳ho{C/ty5u2/ 41)?zδ\pv*x2.gy43Tɒe2Ԉz 3\c7!P%|UG1/3wJl鎴 c3^=m5'3@N+4cnZK3`92@P"8U(3y?p4_} kb3(In4Q{3469Gc${荴%G5Գy3c4Zؙ WU 5󲝃#ߴizKu㳁 |XZ&[*)M2q۳K3$A``ꓲ4,4LDl3)3zy3г2keXY4bf;A\ !K4[Q|%)dtԳ%Qx"lu ʹ}οȕ_S^CĴ I&q <q*2ހA_$mȳy&( sIqʳ[׳'3 b9$4Sp(3:4H!t%41dܴ}Xәδ.+~К۴޴Zm*$Ĵn(EzLIQO; FHn.Ɠ]ƴ0R@3w(#4YLy4-vE۳Q@[!4˲ka s[w8W7aȳBu4v_Wδ xLƴ.{ʴ9=ĴGy`? ujᴥLgA۴g/>oFeZ3؜1ϴvK&;(E഼J\o㴿ͳi%:7mYo鴢 ٳcwK4Xj143WvO *?+3&c54T34_m4L4Mi4˃4xb3U3ze24s3#^4k4V 3ϲvi3d?3Y\s4+t8}c*"2zL̋!]l6nR4X6܇3䑾368rwYfP3ؑZf4ETԴM3nƴ ʴ&hSV&سs3'"3!0B10.%%+ݴUWVoH\1pP9賗%fu& Ѵ޲'Uxgz4d =ɗ34T7m4a37/^492di޳0$44J33a3V4;JZaqOr'ƴgӳ 3*tʴ1тj!V2}uzɴq}3t4y6M MDzO6zL+Xﳸ(G02k7c mř2j( 4 @WFxf3|2v>4&R/42Y4&2M2WS'~G_J2'3Y<4%+\281'|?D733Z R3ݐJS0 z4\qu{.4*4b4 5f~444y5F5475kx4+4(5)g4 5@'>4t4/v4w%4(w4Ϻe= y44H5,4 4Zv?4d4|r4c64-4{~4u3zU3MD23.4 /4+&54(4\)3g*8Y4KD`=]fq44`34բ4l4>44L4]4e494f׳D;s4y̳ i\3w24&+3d31Q$235H44844@;Ә4z4x3ޱ4jz͛[q45S463l$3nD4m_4)-4H4_4a4o3[4 4/425o4&Ӳ߹32`2"97U%1FĀ3}߱o4-63=ʹ|4ұ j3糍394_|%8P330FW3.Fr4-4 Zq1s34f4 tN4s47 4}(4a2sU4;m0 3F 4 44+44~3Q4w;vt#%33vy2E%))|(WN\imH*)3R>l$bm|%9wLwKL 5xƿ{]w`__IϚBt@ә2F4E441A3(rij(4웙93xxK{y4G'-1>2ǎ3m {6`, ~?4H4ηʹKϾ3L3z4M؛4c7!4~20GaD4;48sC"3`o 4hx U)Yd!,,y4SpF2c2).Nj3vj_"۴8+4o24?4>O333x41h xs3쟨43H>) 1N1>k'}4;3zt434^2]/^ϲ_3~3ʳ#4>64'N.4kf3,mT1^5ZJ <ɂV3VJ1~3 4 4I;"Zb2l2ؑWW2ܳS3sU?92YJ2γ1;x׳b7땲cNp.׳=ų5"+K~4 1;4=zδGc4y'r3$h#.Q32m4T^ݳMմHN{ oQ*u춳9HϢ&GNK̏3me2 մް'OY;鴩`GsZ)T/Ѧ33ll>1s}EWD?u ٲpTw2;j4഑:AvMQI&k37 ]3iڌg == r_!Q4(մW ī烴,Դւ\R' C pشUu70s,j˴va(]Ⳉ^i2PQ2D: u1:3Us}Y@ƴ4 _b+o[my괫e? x:9S u&i^^2܏i˥_R WbR3z\/h`ʴW;GQ{&ˢٗƴk3tߴu'3@)SSFc?3 }eP GNߴYȴS˳P:Lh: 09elѴEZ0"A$ʐZشxʴ-Ym3Տ1ų)T ǴB+kܾ=2^E"^74ܱ 3_42fk߳I´\2-A33cV4=cJ`#i5XjL4eִKJE53(44Y3eT 4&4@4:P]UXNN2; 2Cv404,"hD4'=2䓦X<4`@Ǵô'umj.B ʴiM4㲺Ǵa3@឴Iڲͳ(bte7 aEڴݴ"4Ձq1t4r{D4|4) 3{!54۞3:2ӻS2S44# 4N23-4b4*yx3|d4#4~4;U4>FZ48C44bh~Z3O4?3G4Z4|tV4r:38&4i(44&4R%3x.}%3 \4?A3a3p52D 445bac4u_44|ۄ MrO42ݾE44 %44Q4&.4RʲQM3542H3_4~3D4:4A`3qX]Q4vl24O2J4W4>w3U3D43*44-43$1z:45E3o3S43"3[}Y4ZW3k4j48M4sǸ4>43i4.4 -S4C4\s\4OZ3<B442\o4?5-:4(|44&4m!4ݿ3E4:4)433pe4&52234h3+ؐ4op4]4$TH4oٜ44444^ 54zGU4J<44M3'B44x+5&5()4~4?4|4D35H4>P4'4NE44 d 5F4!4i4BW4F447H14gJC436055 4x4484e45n/54L%5@z4s&4&.4w#5d*5+4444ӄ4 53W+484k-3\4 35R[4ƒ4Qz44S45 4gNԐ4J454745V44R434N3L34k+%4Y4n4%4ݯIj3203ŷ3 d3'Z43^Xl3g!!4َ3t_4444hY4"ù344@4k6аd"563-3z7vW4 J\"4ܢ5ݑ2W3t4&3m+35434V34=44@沭3 p47r.׍4uT3IE!2hGi9g{>׵F%Q E5I3uI22*42#`8ʴ5k!ؾ 5IO53yc474R/hʁ4ʱ~224F p4sr4EqK( f33K&f 48,~ 43K$]-u2ՠ(8%h2 h"޳bY"2{#3Pv8X4S+jjx~26e[D32$V65mLq4 3J833܊K4s4!R'k3#&3mU̧43T UZ]40VD޴޳ňi2޴$='2n\&`,B~aԳQ t ƥIbԴ ƴe8:raAFCFϴ' E1Yֲ+j\T̈ΆtiP ij|"n궴3Ѵ˛_̀شyB|Vְ^x T 4ٻ4$ƳlؾlR}*I+ƃ$/ƴ+*uɴUh7B22Dz$ȳg&ւ똴Ӵס=123b4V^92 rT6-@<2sK5F3]1 w3?2 ߳jRd?޴C3[44[ 3{t3|΄4g20!4B113{p3k3q볖I4ם4 m49]kp45|4zś464̳Ǚe@ /=|4 4GƳ3Оڲ3/43³HV442F3)[4,/gPe4U_4B|4Ŭ"4-4{4=T3o33 4d4*4S4v2i4e4c4.z44mm64m544H45T4x 5B*4k5!!434)4˗44$j4c4R$4p֩4[43 A43?454,*4:4|lJ4"3݋35L4%44𤳸44a%S3L7$4Z4mC1mU04G4&3@4I4-wr4 3>3C4G!=%4w4?48Å3704f(,43!e4Qv4"EEv4z3lPa43C>LK4 Z3$H33E44L k4(38jr>234m!Uj/>س3s4nr{3Ž=34 Cb44O3i4忱Q5S`44"33T-4 4ɥ3Z4!2Y5Qv3J>4S3G4[}h34ZFO"4eT2T1a44H 4hWWu4,.4Ŀ3GZ4M24@4?444Ơ4 3Vj3<5$c43^%',4T?44kH1e"4P`33jI46&3٦ n33 Z[4vc,13 rΡ/R}HJ%Xl63i5Ҵ@Β%Ѥ㳢*42]33{4Vس@{4,a]Sl#v閕2\34w3]4^j޳|83$4dqWB4쟈4z}4H+43^P:3 㗳_4/d364<44~9i33u4s44iD4#՘4i33:34?`4Z34}3|@4A4W4(4j-4Z 5Ѹ44n 54^4:"12 3@%4I_4J4A432nm46ka4i>4W3F4Ν#44{4=fQ4J4h44#054r4605@5H4O5f4%43U4/ 4t۳44˷44.5 5h+5Og4>^4К4U4gl 43&5G4Vq54S*44j44A44粘F4kߴ4lr4S} 5"5&5b4(i58p4m4U354#4p4d4˙43\$4E7?55_4x44344 44d4LXE2W1R4:4[n3N2374O#4 4ߗ42q4_4 w4B12>,q,XަG53VW4c4 f "4Nϳ"K3W)x1 4p293{46 44ϫ3DwjeV3(e,4[2]ɼ3H:3G^444ݳG$4=15nЪ4 #44Cl4,S4!44E.~k4y*3(3вqԈ\N4V4x?|4CׁhwH5jSDt4y4T똯_l4ն43% 4 #xŲt304 33cW4^^4J@4Dv5Y۱14Q4Ê4q 4,Ri#4wE4ξ2MpS-4Ӭ4ִ2EG%9FEr24Jbk~m,k4g4c\&47!8 4@4ۯ~e3T2@v4<44MY4l(82x4ij) ,3f3X)4V4X4̞3:سr+2$3Sԯ ˢț3a_VIu斴J-⅑o3_*435y44+43O4B-3V鲄3E?3343m4p3?|4 ,927"2 44T-5AD!r3вg`a4W_̴ѳ# }ᓴJ#ߴ"w84 #p3燾xi2ӓ33 3㳞44N@s ݇3'33R򸳔Y3,48da3İ24e>4}ɳ3dkhN2O3מp4>2h{ 4Ѵ l3Cb2V8!2bN55%D$3?M3N³D;᯴(_{Kf1b YT :볬k" ÍS級g$QMZbE1^`2=243!5,8VPI洡^򴗚k 4w{[kL<-kdִrԄu|U!γz%a3R´ˉ 9JD@K(贡?Tl۴%쾴7%Y3KP+S4EmFŀY䳳- E i T1컴~ÒzMݓ۴I"Z[ğ>8H;<-ӦjZbSc$nQ\ 4 `<LŐ-ic %xʴ=ŝų`aϳWU@C㥳e}Ӎٴ) 2yֲ"3ں,3nЦp䋢4SsHQ93W2 3ː2F]4,D4`~۴)t`JFI6~г6V0 4@3mK/%kz̴iX .H lAN7d&{A&VE} .%yF.ZiPcR[K#2e*ݴ@RwA1]: dD yӴUOWrs L63%aDruqӴ{%8봩nP,ɴ̝3Z{Tx4E::64r;4"q77lp҉Kٶ_FF@%ڳ~' D:n,2oت2PVH #{ִ2jb񴟻6V343xCu40?6K̳޽3ziYӳ`#53 f =o&44Ys2wSٽl38KۇQ*}k4r$3ꤴ]ok333 4z.H4TY4H4`44454P3keS4V34,#534c/4,5^3r3 4]p444ԉ4vH3Lڈ3%4845F464sy44'4¹44+A4_4&44ݟ.54>4~L5X4SO44j44 =3.y4c*54I?49EJ5; 5K4(&Ah-4f5rC4kn4{3749~75 4+"5.04!D4442,5p43f>4V3&444 54An4%5V_i444 D4F4D4G3P4/4-4:b5405<5^4[4gv4%14H+}54X333HA35D44xG4M4*'44>X54ؼ4$#454™U4i4L\4"4 5J4&5B5-5*&5~5c/5h44|L4n4=:4=e4N44{'54}4!4t4E4423Zf4Yl4"^4\4]>3X4q.5^4k4 4v?5N451544J5p5<_4 4954{&4D-55O535"55B5Ha5g5t5,/5%4RN5?5~l5݌(5r55jk(5F5W^ 557HU5]5O5B524hy4ma5h 5QvG4b45=5:l5'[5nz45-+5z4c5{4R35U5³;54-=5+55T4P5@4}5B552/4ʥZ5M54؂4s5B4+Yy5º4-65C5u5{b5455O 5*5[C5W-Q585o4S854 5s45`=455%M4s4b 5C05$5)_4Y"5*.5r5Q5Y;5I 5.85wu55Y'54 5]4U!554޵3| 54415-4dv44s34@@4u4wڳJ3vD6+>q2H4R2a/N3՝3̘g2KŴ4?3:6nȲ90&2?}nH)2Enw4ԙ4&4M^9as3 oX4ĵ4ހ2Y3@:[3U3 C4i (43 4046Ѳgȳ+4Y3TF45\4᳘B433?-F;u3{!x24^4 RP3t435bF&*Ɩ4Fr#X437<)4/4/^ɼ,z40&V"I4ؽ3}'3׾{4WU`04ۻ4cߪ4434;?ݛ441eP4yƐ3R4b4dJ445 U/34B{4PJ483p3q933p4M%4b$ 54-4,4}3<4N444/d2vy:-%}3JбN>ȳL<94(wmϴ΄2`0f3JD4SbW)38_20 3k)Ks3Xo)z,ZMfÛ??t22{r3~f(˴Pǖ޴K೅#1Ŵke5ٴ`XE'"B'H*P49 :34@1b$H1Uv<:b U ִu,"Ԟ޴7Y&"?YoF^_F?{a4=Qj'L/Vx98jYʹW1!!lдD7 @h䃴yM~EF´ssg'S:ҍ$9Ra(B4 |ml$"K'$;W#kbW>DR$v D5@l8=i-ɓwlPD_7o@9uVǴ'~'a:#$%c*-P #JF1J+5xɵR}"!?7!4Sߙ&%\@KdCM2i9$x!lȴ` Nhc >W1(4B % ޴tFuִaش,Y(ٴ<;>#*t?("մZVAm-]6pVDs[N)?({` vB\PkpH(Ѵk7B1+2(tIGsY1M,_;l3&Zi_a.%*̴\ 8lF^2Pt+dlp ]ۙ_1#'1׷ QO~X[JƴHF^?+EߴXOnގfh~PY=>o~)Va-v_@6S%Yh!ƒE ,^ H-??OJҴdr* Llls/bt?-xkoTu|2{œߴךV3(hlB+Hs8ȇA43>4.7зk N4p<2/ 4@䱳ei4#Y33/,jc4v4d3YUu3͒2K22 ]4A4za306473_44'4`4н4 4q4j3lE49z44̞B4SB45aH3q(b44Lo 54 d44$4̵4Sx4v5w{4384%43!4=374u3/T%4D=4L4L4{,4c42M424y24é45*4Ύ4[i=)3:f4%.4G7513N"3`43}4Ńy43pP32B3'STu4c3%R3pDZ4>44g[a4Cv4Eߝ4]5Qi44!A)/3%T5,5942Nw35R4C54<54^ 4m44Ъ4y34A55G54~n_5%475]4!5/5s'4K4I4\4+{4U 5.5h5Ka54u;5e45d53(55}G/58$5پ4f 5615r5l5U5˾M5+ 55'R]55^4G54"F4P5NT5aϿ4))+54<5f5! 5vQf5M5H5fa5U"5575G5"95@5~I5(85("4ߩ5Uw5wE5'5ed5L545T5J5;5'O54f5u5,P45Q5>E5155]T5s545 4g45 4S]4S4^3w\424EZ3:4ã4:2W 4ڳ4+.|O 1tz4j414544p4ڝ2n5444w44}4l3)4@44 3 z4ܣ4=uN43ut4 c%4{3˛4.ذWڲճK{9b3_xM@Mc^03ײ쐴34 }4a844#V4a_3+3QI3)jǍ]4 a443o,f2;ųm$9c³қK3X?42޴%BTڳ>Y)ѱa|-3BEEHX6ɳT_X4g4V*7D_I_4E\4v1i*33NNu4R2k4[72A44:fɴiѓա&3~˷㻪2r%̴FO®nVWuD?=ϴjpɴ=%,$#]Y]TR(kA+[ %o3b4c6TGִ.ЈqQ*3SuᴸҠ37wҴ/傴):܆2:Vj˴κJ񴒻Vg;|V~BhI :SFǴm`}2ݴx&E- [)<p [)Ӈ MUUXN*e1&.ElH.+ZB&Kd954mt{4)BXbQ Y&5ڴvGB$C2c*2 =-ؾLF~uO[a4AccDEXRJ=RTn>zUu?TIm8dLUֹ´mu-9 4Lv8ӾJ⥶7-s<"ôp +wĴKiX&y,m. K0ȂR3[ϴWX!3$`qôv3aJ3Tx4]0IJ i5K]3`% 9,fδQ-4RQRԆl‰|B}" M<#̥3L3we 'Uഋj,D޴{2maF0<3R2D3xhD`lH 130W34*4ش1̌4R_޸EࠄZwدd@;. 3EֳJ# oZ39DR=u|ﲰ 46 4h-U3Z &ӴMF {t#D[&ɴ)Lʲ糈4RoKsC4/r3og3`˳ϴU"4[{3fN4 a4@f4:i4!9n3oi414o3ұ37E34073404 325å34Qk3"42J^䳎V4{!3S3}56402\|*+ֲgɳ̳jK:{C4 4y=1"b2= 3S!4)442仮4$5ۣ4@L4<43404Nj41244kIJL5]5i4}4q˧4L4?+5b45$544'F454|454'V4%;4a4w4ǹ3`=4•4 ԉ4I!3 r4 4d44G_P45tߝ4F4%45)Q4e5"545$4J4CG44l4!m4w744iU4(.5ʠ44׻4{5D4Mѳ@4J52<3;3Nɧ4٥3S454;4] 45535%5V4l3@4g 4;4BQ4z4`S45I05 5$55m <545JA44Y44kW54*44{4B=Y4 4,dW4T'5j4 44Ӣ4t54B4545K5)O4 "%5U4_5ȉ4Mr5,5:5{H554$$5^ 5~74D5g34y4e 5-'54a4N4#4552H48 5͎4_444J4Y444iX4P]4n4t3441K4!4l4[T4F43IJx?4X4:z33ir4$5;Ա[݊[4SY3H44S*;4d4΂,32 4 3hs4rn4a42C3<4m41-@4EM4u [4u4Hv2 ܌414 44S25=4, 4BW5N4ZZ4\ؕ4 5S@55 5>:4V{5}4;5a4t2314VFҳ4342w&짲4#ŭ4 1eR3KO2Wa4534N1N4>33 (^=3,7pۢ34z4L'Ͱ4v7/4CY3#l34L4Ӹd4vV4-9c4YR4 4ݫ44V45 5)Ӯ45ܹ44VY4N=4/3v45"5@3Y4}W4S45FF4Q4*5&%5G44ͣI[4z3444ⵝ4pD4ә343)&4àƦ%2O4M(3:4ڔ3kx43Fh4 4]4u3 =44^={4 I4\4Lf44, 4,S4(5X]442J4 4bl3Gd3są44P_4Bc444?as4l3K444oƳMC42 4Sz4k4v24U45 5ET4244W4 34>23K*d04ޱ =3ڇ4в5&3^au5V#Ŵʴff~pചJ+5?ʹô1Mcʴ#tNgOAtش +سT,44%29|13+;ZFVô:HCSNCƴeNH4uoʣ+Y4yxF3%-w7G`h E3nr1M*Ou´C4 llMY$J#c9ܴ(UYѴw2nYٛng3+:لW32Tr4DzB&l 4 9f3pOϟĎ3;jr4v4#Es 3M4n484j/1k<0}bD.cQXaJqU 4EǴˆxƃNO A7HM[ xt崳Vߴ^H607cGrykVf+peY:;SF~ #}7eK đsU j">Bf(V밳EB Ŵ5ǴBŴ lW紳] |,櫳XYx덳:Mz} o;%Q[C w޹sL;״%+ɴGشZԴDTQD 񴞤A7pô!43'17*?5״la. v&)״FOYeTٴQj57 մf^01љ[7&4)nϩ*+IC3#6"(43U3Բ3&84/.3收={3l Ec444a4Qufq/n!ffGִ iôm)LOe3N_y;"1\c=Coὴc] Mڴ8wۮ\CȾbѲ04cSL o2׳J3I'n4R4Gw42߳Ē4Dѿ4Ψ4%4Ǡ4Ņ4)434/O4j4C5J443-/z4䭲B4q4S75~(5j"N4&23 3I4@ֲ(%4/~4w4HrA3@=4[ 5K2Ds4e$C4=4}4qV33<64j33ۈ33m43Y/4ٺ3%A41J"$ϲM3,/sO44_ؽ}3044d5 U4 5{;=5"4]455';5?#54`I5C4g5 "5a5:44.'484i H5o4D4uf4{m4d4ǭ4ޥ4Η5}v4 5,2>w4 4R4xs5={3Փ4u4d43"4f14)4R <4|44p4Z4`4f4ӝ4]2Y4K4椀44J04y4 44<4艨34w3 5FJ4=3G؃44f43x'+4`0h1{44 oQ44]3%?@5Ԙ4G@4ڊ3@$ɕe3F)3Z4O贌,][kG :U4ㅴg 7ʬOJڴ?gf= j*:!K޴;3?@Ix.3d4x 4mE4|W4;3Dņ4h~4a4Oh4ٕ4p]44ҍ5*4Q3a4ь4䴛4i41ى31!4z3p4Hy4Z32)4ح4*4R22"4س.(4ta33!⯴84\I._3KNY{)&.2Ă4i<~-4<>uoI43=?4yE4ʫc4 353F3o-˳<$W~4L235w4M334C4sD44Ӌ4f34B43'4{C4s܆4a4_44ޡ44OH4гQlo3m49XV4\T>T2Ȗ2ǖU#4I=ŴF7 "Hg;VHx69PS (Me@51Ry`ཆϝ^4ٴfw3U$T>4Z)ܒA44A;v)2/T(2v24 1IXL  Y<1֝Ŵdw%4 3o`fM΁xﴁ<#P_߳~7:Yr^}3n. 4|#\0JCGBx֌3PXaz4pEǴ" I oŴBhX+4J44}W׈2904E#3N45#5 w44:4x44u4=40n4Z2454 434Ҩ5Y45l4Z)5v3#4nT4h(55"4ө5H4(4>44Fv4}|4p45å456_364]4 e543j-4ZE4z4.s44 4=4+4L4p44 4L\4>߁4q4n4$4 4|4'윳H2 44I+:4eG433kd3|;4O4Vy4I 4pā4Y!(޴2޸2Vܔ4٪O03364ͳ zkwT354x`1ppi4Z4IO=9/P3 I2cS<֏d22|4?H43Y6 _8C޽[[4m!21uֲw3!3vum!:2$ 83Uv4n-|hO3!@4_Nca484)q494[4z=1ݢ4%64k3}S4 F4w43~348464a5!4y4$5/44X5s*54S4T]4x45&5{'5y4ݰ4a5R4 44)5" 54~z4@45\4^4żJ4%4xm458ʲ35$4^46p443U4146a4ʂ3.F44e34|41 5K05.5 54G5'5T44"554n/5 55O4^4[5vO565SOf42 5 56D45Dn44R4rn4fo4X44@4q4R4Y4Y1͆HU4`4Zlrw,Fg3+(%}^rY4'33 4 437(Ac4:73 4˲U=4p44ɘ3/ 4wWвm121^[/,{#4MY49{#3t/43;-4Q3-4j64?Qf4z3zi44W4,%4u4L[55Z5m4L4!4L5a4Փ443U2[3شǍ3~4-l3BWxʹu7粆운˴%3*ѳ4122xLd~1=2)33ы45^w4D34 524Ŧ5]4V405:י44E5ǥ@4rh44X5;" 54-5W4!4"5yfK55U4=403s4 4vU1R4W3x4G3443A4 3֝443 345q4'i44#3"4<34]#4)5|4tA33d44z4 !4y4844\4043[44Ê4?Ŵ4E4v 3ՙ441T4& 4gHG4vQ5 94e4s ޏ4b4C44; 4034׀3U 4En>5U4554"54׈4S4I58`V48!4 4ܶ4/44pb424Yl 4lH4f'4KߴVҴ8޴BKpg0a!G>ϴ[ Do1-1Ez<㴨oѳ!/3 д 4¼Ό1\K34῏4744H4?44V4ys4!?\0D 3#335>D4zw482j4ՠ4s4.J4:Nwl޴&F봖'I&4-c3/ySӴ `r vԀelݴ$oLbzm Ŵ_#Op',L˴qY شS3:@@H㳺22;-Ѵ !\5՚qVLô_73wL*@y4U4 k:4`62Wt4Ls)~g\K4v㳨'}kS3S3_ &과}33+lS" LƵ a_G~´ E䳉qvֳHʹ8 2#8%53ySy2r3@=|/r2:74w4P3ڢ8N4(54S4;4UH)43o3!f4#3K3}ih4/s2 Fet44-4ڡ!0>0{D4$4mr4;44y4Z41W4515CqA4 38@4rB435ci2A3e43%f4ϳ,2뙌463Qq"4^`' 25u328ʴ2#6ErZ4^ p,-49B4?q5$14DCV(W3%3Hٸ3 |44]34r4'484/5W4!4MO4x[44ԧ446ٓ4$4444/n4(544yV3[4a4@44!4x4>4m4v:5P@4@4yt4d3[*4@ 4"*4Ŀ;۳N4|xV4.#4Rt4Eݸ4֗44ґ30綳gf/|44s@4l<4g444544WD5t44-3U4B44 4z44 4$p484Ԛ4:4^4It $5 4Zh48\444ٍ444584 5R4k@44044գx54ou*55|4r4W4 !54:4Y4wY4xR4W5fG4K5Z434Z{4_134>24n45*2ݙ4 4p45H4z4(O45uvc44w45g4ݔ4w$5z 5Wz544ey5N:S5+5Q5+5_535~5c܂5%54k59H5#5hP5y58L5&55.5\5|Eb5%4(55:4{5oY5=N4'*5H54Nm 5¢5<=5(45}5sl457444? 54#45`,55444YH5eM+4zQ5V5!^D5u4F4R&5d<4b5y5A5%5N52\5J5b5:a555ӓo59#555L5gb5N5~a5s5b55f5)/c5i565y5Vx5_5h55}5j4ښ555z+5r!44N45w!'4 b44:5\4`|4䣕4 t/5gI4;4S4 55!.5W4J5>4p 5 444q5t14%46O5ϢM5kc85:A5D"35 5?65`N5gN5S`4cP54O42575S4w 5'5|k4L55065mv4l5Y 5a)4V4w5}4?̪444xV5[4GR5l41425455&5<4~x4:t424❇4ކ4g35 5 $5>5a45444)454^T5#so2kP4*54 5H4Lc!5 5{4M4j 5ׁ4d?5sU4P5ge4c5$\75&5*"5?4m45s4px(5bn4!44{R44443=Ȳ3 4n4bՋ44M5Ĩ3p3Jg4O4H454!44C44Z4/424k`44*4Aԩ4Iq4X4^4b o4'144c643^94 >M4dn4 4Վ4.4 5vF4a44D4!\40C4U+mM4}Z9&B44'4N@2uׯ4da444;4bA3Vg.4d4qX4m424z1/3~Zh+CCl 3X|aPشY-bU/+5 dz3Ӏm z'QĴ2$>sqMo334$FbYٳF-)S۴5D ;FEʳb H ! yw*F> >괩p%rU9L_w'lδ+z2J|oiߴx*HfYd% 촃54S 1M'0qBٍ촍q/Hc# 0h*3. XvBiZCJ)ki&8wK L{w΃62r@ M2{>V+Ӵ\l*մT? 0l9#:e9 l=(Vr?޴-Lqf| 3mZdp MQGNFsŴ_ Xɰ Au~=ڴִ4>k 3Z҂CW։]hִ~) e /3!:@6o۴u{5.2sκ^CXIa"+Vv(3& /*ȴ g1ش|F"2oNdA=^ *(5a!a71GA<ZS=2Й޷9 @DHS5\ߴ)Aݴڴ~ IB [#,!!/8//($BT}FQI([H{X.ŝ%^ٴ Dk?Qy(%rTeRHpnI0ɺq㮴ʞGǨZ}/#'ʴ0|vNV ւ˜_{8= ˬ8HdϴO˔ճB~q5[Y/alm3ش],ʳYƳ58g4IzXHx~E  .Uϴ D%OS4o+?s':4fTjf%>eӛ0 <w {l#:JceП&˴մc7 Ŵ{<2iE:^;؝sa Wߴ=!۴J޴Ү9ͽ%òU)=R|W7rc)Wᳯ}`\129nONAhRg1 Qڳ-q31Ed@3^D;2/̳Q4yhyb3%d4铵3 g3q&434.G43泑/g3BPж4mp2y2rQ4~ޜ4 353b5]4K, 4S4(4v4?4G O444?3Z4.HN3e.4ݑ6Y4F 3J4uX&4I貗<28^B3 4N2C?32Z޳v3r"4M343 p4v&4.v2Vb6$.9332o3zf5[X4ha4 O 4DPL4m42x4 33Oϱ0}M3ȿ Cm?84}|i3ѴAG3;մeh⡴0F4ڰg42i泫83~/3M6G3?4rG1h4'CK4\/P-o?{1]o(3`74#Z33\ݳֲst߳4H[4D|2>ڴR2c PnBnZVb0U|h8"Pϴ ?"594pٜve 6Q3Eﳢx3ӄ"?3,F3W34y~&34Dx4MD41xH#2G4־4m'4{4^42,N543v5k!5" 55/5]5?5a585-5Vi5}44(V5X5,@44OK4y3494xwo33ɅG4PS3tY4 @=Ⲫ3h6 3<40=߉3ԏ314:3b4R\44 }4ޡ1t4%"5޵4.4G4,4 4l4m4rB2 44`444r=zD4dD2h4͢44Z׆35 4R43~4*"4^4J 4#% 44Ə4444ܔ4^_4G4-4y dz44'594^$2404cI4)F40s|4E}342|5f5mԍ2*1d3P24μ424kIJT_4S4K5b/5ݕ4 z3!5C14Jm4{5bK04y5ȸ4 5745+4J4\^5 4o44M{"5@>5F5V4斜4 t3~4j+444\5}G43+33M3 >4͐ 2a4 5"3a44ճiW4TZ0$4Wv 2+Ј4ŘC%4]1Y3ˈ 3W+4O4,4Ù4ňO-4`47ô4 m!Wiul44JM34Sy5r)74 14(h3Sȱ8AfQ354`^4B4Qc4!5xU3nH4A>,vLQ*,J/[Fh3S.V|4"4$F&3@4/rA`I:Q*kg*: oH4h4ZʹrKpyzmL.}N\Mc*>1,KfTb44dcO^0Rl7P!3Tkj`4G+4Sxjy3_4 | i2d_2ft34 05S3[3Af4?3}@W4Y1~G$2(RߍiFwsn4s:94nH3 TjV㤴-Դd_s;X [3ݴ]1ÌgCWE%D`ݴ9)`Kg@OyD׳Z.EQmJLfO]>VPVoٴ"I4R,4L_3Ѳr4t3X;3Y3>E. ʳ4Iu⳼+@3e3)4y3g4Zm 9D7A)̴K#Oqk ﴘϳh֪cј:Sǐ <2( `O_1 H  ^Uv̴7F)ҴaV+K|t/ڴ*o2p;+Ζ9efux<#3WQ3ϳ;/mh3'43M4a4z45c3X k{4%4) ^T4 3J, Ƅ4JF 1ӸY4m3244.M#[E=IW=[PgN˱M]3R@2 W'ӯa-qnEeI3h̫4[5Q㴵|ٳY cYEȏûx3o^ŖhD^gO2HePdz3j ?nH!4"۳ ޲0|4+Dɯg%h:'}m2 $3Ri'k8jie*}:4_A2#ʹ>и쑿YGt%qѽ퐳̴x_1N)ų1ҔNŴQ2̕|-)4P|4j os4VT5g232ijN6b4>44L46 4-4`4'3 GP&3؋4{{Wh4訖1[4_4,4{UѲWL44 K,]4ɍϢ3xȱ444S3p4H3F3-43; 3<"Ǜ53m2|3<3[4!'4a1>4Q<1?1֫遐24V=\/.[ر_a40{494t4{8%3AV1N 5я3]x!3`34>3N4][4 &B5b2~b3R4u3b@4p4p3&!4 4,44UVu4y4d;3N4{C2O4H!444ҳXF3<44t4&tS342 T5v޹2aǀ4n4̰t433}4[U]4& 4 =4ɗR'43[ѻn4V3|"$0|3Y3`a4`w3u:34f^4Q384\33kXZ 4=#q4.4'4:m4-8p 34.dzAn}44}4 W4`4424v42b3D244&3=C׍2i4W34}3aZ4N34;"ղb4044h4.ab5Yc4444*4=2D³kZ4A;4233g،4Ŕ4`413p4b 4\{44B3%4W44P4540"s4?51]5P3W,3W94Zˎ4H4B4Y5m@143!54Y&5$3;94c4B3H43|$44h V4) 4l(MY42kG04lҳ $ 4H24􁜴o4038m4mv 4Q423 c4?:rנBZ4sƁ:30[! 4]4Il3G3.. 3}) 37h3|*' 34a49 B_$4z3;W4X\#3X3Ŵ$l3ʹQ2F2J444b |J|H2ڎ>}R4*61Jt3&*@4ȭE3#(4ߔDk?WG#5.#qWK0zfԜ뽴pZK^u-)qi&FlĴsܴxulʴ'AJIX̷&I4P u6vLƦ>/"J8TOM,4b!44 ⧔4eX3ui4em4F4C4555G*5"3Ҫ4245Q34M3f5u440q432&5ڤ4H5Y43FF44{;4),4024ښ4-&5c4/&4'5%5: 4U464ZYT3[49r4-r4ӳʔ4`25PA4./A͉4Z|4o44_4h44H05?ֳv4=4d04Bs4c4-4{V4(<5x4v\5554%4-r4\4EX55)944j3g4u(55K4D54U$5d!4554|4<`4Z45Y44U4548554u64r`744G#4 2τo4~|35{@2y4ճ49 14v:^42ꎹ|0?TPV4p "]43\2Sa2{37+ܳw8H84Fً4bq^O3JxaX*+23+O44΢4w3294N4XS.4X4Ѕ4I3o453hf3f3z5K5å4m4M4HU448b34S4S)/Im4I1g4:3!34C҈9&/4p)4Ұ;㴈p"3*|4_4s1 74i%5&ų 4($4A4>4ø4k3y%54t-4w5}4|5w 5C5-K49=5 53A58N35GA5[*5z575*44]'5'44655R#55J^5}B59525WqJ5Ǽ4&(45585/4#35Z544E49)5Ϊw58T4cR5A5d45D4F4P5=K5'4 -P*54İ4^5J4C454X54j55 4434&4144٦44,4#4j054#44s4~15c|3424*_*5a4 5\4\5~O5s4!555͟`4R55Kb4նl3=4Fu4ߚ<4)5#4#Zs34}4[4~44'իǁ (v2}3w3 mȳ+NPye)sbۗ46P8 Q 3Q [\je-iߋ^1},ϳѤ3ZOG]4 a Z7"׏3tPy3FU3Q޳䅳s3R~U3ߚS^L_*ҔҴZvjǴͳݴBX.*a9Kl<;4 $3<ـ>4H,?ճ3"d)RZ3MЇ3aҠ+42J43gp43l4E>"X.35Qp4c0ֆ4944H3VI4q4Ֆ4+4PFK4g4G4jpW43EI44`954Jk44 5}JN4̓44̈́44I*>4^32 LH䵂`35h4Ef3wb<%3*Z4m,4 4-8vd]F2X3D=35짴G3Y4EC3LT]?a3 o4`=;TM2 SKLhq~`(28ȉ邴HlHQݴ#O3G3w]T44|2_iu;Ea4'6v tN2ړ537H 4|2)Q\PY7ϦLʴ3 G-3 4Ϫc3:Bɴr:|$= O!6?sYm7Vh ~"X @/˺-SGE6=[뇴 kYH4SIV#;ÕL4a;g):!JgFXx4C/@3ye<Lsh:O%YX+E #s`#av-R35cdU8S<6P,+9os KTFϴ&/_/I d2'F#{c"#8FJԴY (sPUFAUܴ%qɴUc=w9hȴ9dm+SeC5U Hw-2r-=2`43u\3H]2I_4 =4p! [4vsq3He27~4!3]4LE4\e44o=R4*4ٕ<2u4zG42W͞4ͪ35$yi43&'34z4nw4eS8P43ژ46?2/@3Y4021(4%4{Q4W™4`3lA44/2"&5M4)3.4 |45q4:443p4@4{b4.%4xP4n X4?>,4l9Ee:2.04O4Jm4%4)4nA44(^X4j4:4 t>33p3P(4ҍ4TwpS3! 4~(4ܰ:41 4Vo8Nc!v<,.I%4/fi\73á2_!4R1ٴ:4Vp3;R"7@%ۃS"k3\ P ӪqW3jFmj3rNMM4 33ņ4B3p4;ϳ~ٗ43q4V3ox44 44F;43=ם4S34#;664:%44L44C4RA4 5442#4R495?40>5 5oa4r5F5.44 5a284A7484 5Ld3[4?4+Q44Q44Z4I59454d4G9Z4/3ˊ4yp4'4Y4<34o4*M5[55<45C(5^*5a545s'5]A54 95*5x5{n5!F5 5Gka5W5H5M>5P5O&5 495`45{w5N(5q15 5K5lw5SM4H'5r 5`5P_4N549ʵ4q05?5Z5G( 5S5P5:5XZ5 N4SP447@4p֩4ُ4_ 55{X55>5V4ĺH54a44?5|G 5j4ڍ5̓5t4V5'4(4 5T5mf5x4444X5b4%5d54 5H4#5WI5p54ߌ4J444 404}44#54,=5423X߲zK4عx ͛4w [4c94&LO!4ֽ4304镓4`x4 4n;04q4=4w5D 44W44D5o954 (A54I5}^)5-;4 5755U4#4#4?5:5 4(m)5C5J5BX5O44<5~R54 5F4f456y4Dy5cQ55V5ަ4Ϭ4%i4,54= 5 ]4%Z4_5}454+5S54%65S5b44d4&E(5r5<5G15!c54a?5) 5i25C54!5q95xoG5+54W5?54J5H5# 5rQ50 5!54B4KC5t4I5֔-5D4I)5344M5!455@44 K54@J5X5<5S155[x5L5T@55@55Y545e(5 651?5|;5E>5-75Q(5ZN5?54׹4255&5I5-4O4oj4 44+54j5i{y4@443ݜo4yWm3J4$]=44)94*3;2Z4lG4~4d1>ׯ45\4D04/T2+13e /3!{mXj4?}x3r434 5@4-J4n4644(5Yx444y 5Ҡ4C6544~4 4 -54ԍ4I 4q.3y:4TN)h<4W3"4E34?'4Ŏ'o3P4<4^@4n!@42s:4+͎8SL4?t4(44N4`44Sl+2 4`#4z4OU44}4Ν/454(4~4c+Z4Y=75a4ث3^4(5 $754`44,5444\9g4 m5q4͏4n4N4q4fw45 35|474 4M4̞34,wKܲ&4 z3:4=_ß54Z4T3ր<4狴fܳ]T$ۃ2?^N4@@d\Pc0n$5 VƎM ^2bYȴ˾30״0=54IP^XDVk-ٴ1i*SN8@_F|B|}!Ŵ݂l3?7`lP3NΤ 9 !Uu Hݴ"h'HMĴZwJдI7ZʿڡwRT)n6yS!4':el;GM{{qvO4ԨVz~?BG‵V$#P_/h'T!2<݊uvbK>6 J1( N1s E%0 )FR c)/^L(h>q^ԴC`r ϳЖ)Ŵ.iR6f;tŴlQwD-#0E {<0ER~;C1Lr#Tk{R sϴ) "T=W-S9 >jq,F$ V8M*l<^`fU!3R)nIXx_8 uaH %s0q/K#@LY3}  X_YNLGgBttѴz0CԴo, V'`@S OuYߓv 1!ڴ(@"FHy ͏&2 Hh{.gEx@F B4ëY/C.'vWo>!YoBѢzq76NZ6P ` .cYA4EoӜ9 l*1Y[>sO>n"aq^?V0,L^'۷ U+3ĉڴ$0ź#!Z9A1?̳YI&g9n˴޴޴0-z2ݴ/ ,[]VsN"X:W߰U ./Ի32?Kb[w=Ƴz3(*TB- 4t_)3 /*1y2DPx15HFD21C4o3`\DQ3 L ߜ44֜4^[ʅ4pN@}3x72d4fܳ·}<4KQ3_j4<4K4RS4s*T4:N4339,4.5s4f 5UY58i44z4>u44=444ۺ4`Q4ȵ44^M4S565L4'5N4.d444:43144߱k̬24N5D4ьx4 3՚4C-5^(534F4t#5,5c4g4 5{4,54=44Wu 5e44,5Đ4À4v:5z5o4)S5e?5c4Wx455V5@@5A5mM55~5r5B&5@4(5L5 5݃58 O5P5*5[z44#?5U25y55wh5C55 55&)55o5v 55Z59H4`K5` 5'5T_54944G?55 5h"75G5r514^5&R5-_U554$5ml 5]454654C5ґ4E4DE 5i5;N5i4a5P55*4Ct5"z-5<"5S54Fj5445 5$55!5]85^5d5)>5φ:5k55,5B5Q4a 5lB5L^J5C5y5ߘ45u4t04D 5G4K5Et47`3s(3dY4Z4S4394".4I <4$04-v !}34155q3fM3p34248444Q5VY4wE59`345344Z15]qB54B54 5z5&]4#5ŭG4JF4 5ֶ4U4c=4 Y4>R44 V4}ƶ4v404Q4;5IG5W܈4z$5 "444d3 54*?5 5>5MǪ444"5v45 5S4sP42Y4e3>Y5&ڳ>41ע4"{1' ?C34j4753Ĵ4&S43 y4y4q4%2>U3;4Ob4D8=3Ej%54t4Ph4s47<#5P5&,43@;4'mh44(4D4ޘ44^$544V/ 5`/4 ( u4C533ݧ4vg4C"P Ky״8}3HN3bh=拴Xۜ 7Hsx!Al?+2aӴ%G83r̴xOs$@v;UT4.~8Dk 43 2r}>H3^/3h G2Q M4k3 ˋ3v,&>42}pTk2SnȪ33KE";K})DdOC/TGӴ 2hд3 &[:֚w;ִA@ 2Gg*Z.px㖴´vxl̲bʹ۵Gl1*o3zMK3h3K%4O, i1cͳnCD>ZEex3Ù39Y_taK22ӝ$.4dr"ֻy#4]-Ĵ4B$xUִᴻfCbNdc?Rre>NO)=0d> څ&h5{HѴ"qXw&D2.M4$n5b`+j8nA\${:!J*2ȕOjmn7ڴٴd'lu$9_j9?a<81R6B7| onb%P2X(L"phwDD򴷅ZNF2*p ^C[ (%cjA'{BS $J`W(:Ҵ.&7!ND\c6ŋ^? M+;bx^+Fmv2( |^:F  촾V7F2贖}d:ڀtJfA:lTSY4贶Ŵ-& ȴarǴ_Mʹy贁Xf6ų;tc6`ӴJ"&BEhEܴWqꬴ,<I ZZ˴o;2R|Y.yJcW46`O:D@3;8}1Fm;sM@մK=&3: E&gd{G3a۴V_ܴtǪyӴ?"QO鴬IJ=#hU&\t-{ٳw/Ӵ|$ߴ:d;Zմٴlϴ^ &X{dƴx $ o՞c,VSҴ_봮pEHo >LL?Rșﴭ/{(4JSDgG(Eox(["}?쪴C޴fٴ -Y@ ?4C]BZ޴P@n$O0Ned aܴ>C*ZҴE8 дʴoRȴJc3ͦ^ܳسÄ&AI R_4P03îP75}ץY4ʦ.-3] K3O48Q-3}4xz8l2pE4bsK/Y N3r#m46E`2'64?ıDt22ͤdǗB2M3/_Pk]?4k; 4(拾;#ОO8cHS33A2B4p3՚4Ho3J3NH44/3 4b3|2O3G4_,4ﴃ4R@04J52404OZ4-U4U)3>3Dw2&ڈ^4[,4'.:R<4;3cXP4X3˳hj"$4<׵3 iju%PÄ32܅3سvd 4IY4|40 574[BXc34I }42s4[\4n3㚳r4ᖜ4az4Q.32 ]S24%3$NFO4Î򮴥X+Դٵ'44ڒ142#4AVa4¨4d45mڳy42K4 43{434 5S5455Q2}5e< 5d75$95H5i84a5+4$t5"s54M05eٙ45s[4ŝ4(ƒ44=559w.5@5,4֖4LC5{5(54 50!5" 5:4;5+I35 5 &5G5;4| 555"5{5T4{|4N=53 45 4-5;Q415(h}5Yx59'455$5yS55K5E8Y5D4[4ƾL544Rj3z4})5%5'5?J4N5 5j4O5?V#55n:5?-4m5@4wB44U45}4~4{4k4{94NS4  4 4_4;55,5j4h4˫3y44V5y4b_4 4 404mu3C4J43444Cj3Q4Bq3-Aއvs3 7B :5顲_\4=4/4G4VS3^3L)4,44 4\{/3 %4p4Lt3/434N45P5_4ex&54b4l44 5U5=4װ35!44o4b¯4485@>444W4|i5hÅ4n54l3bI54t4l$51[4T5o5r~5]=5=5"959Q45M5M5>5{44MA5 5Y49 5|~5 k57Z5l=5@55֚5r5xw5>d5O$5@5e5ڄr5Ա5G5~u5(o5_5rB5ȧ}54Ѳ0Tpc4:3\ϥIr4Jkܳì{~䬁:,δ"xA 92uEij53Z+ͳɳu"o"ߗ#.ʹ/3<44մ*ŴMt3i4M."u3vo3˩?[>41c3N,1su2>o3 3AzmPiK44S G3v1)4!68^3UI3 I49ۅH:3Y"E3 24`_7431P;Y4;31K˲4.'44 W{дPȽ 03#44_$:2Fظ}aʹdnQiⳢEkG+8 :ìw+r5^,`\`gw $δ{kKt6-g8O  ,xKg *7u802~zx&& 9$.`yo!ش TJଘf"}E-ct]6qK Y^7/WdqHgUɴ$G;WC=4(\ܛoO 0Mg01rBNMzqZ+_]L Mn$ #aC?.,lL^VV#ǂ>V3I|@lyRY~oU?\KUB";X)fj#"ݔ!SVُ1}e @EXs(D(,h$9+.C2\}QoO,ճ?;2֡մ3`{K9zsk鴅֮Ĵ8О,Gٴ2-RӴʹY { ʴ*AC/t52dq >>n^״LDAն"|3.ZOZ"AGb->*Cr`A o_􁴠$Ъ oC CD$7 ?hfҴ kFʴ}UMx c^;!8ʨ9: ;B'$ʄ )gy)t5c/\s4zѴU=?Ek@) 7 :ʹʲ[*FG 0 Ҵ6S-gԴݿ} 96C;$avI/yUM:u+l'オ5{&2 & 12Ӵ1UjvBkﴥK3&42B4Iҳ3+`8m4AG4-4_./F!3d4c4մ=32{3%;]4B3 c3BB:5> 3]x4W 2ow錼ZV14(44:40n4ϯ4-4Ԥ4S.4l34`}4W 5dU4<4Ĭ4C4к5&b5F'K4Y5 545Ba5.i,5P4-5Bc4J49 5BC5@4#5YI5)35w4345: p4`5i4Q5Ǡ444k4245&4+P'K]4d 5%R4;2U3_4.m4yp4q40Z2 47~4d޼3l4p?bY+ͳ}n(Py3_mrz3T5ͳa)Áf+%3ύM4`0r!5a3-Ct4_3𴁴Q!S 4`M2ݳO1+3f´)ɟ/ą3E"]4T3#ô( 3y02w3Pϕ$3 _q.XLm&3`'[[uwSLUTm]/3bO439L2kơS4@4A;nJT2sIh3kJڲ= %L43134*33 Gq4qm4٩3xX44x444D5rN4?4]@54h4s-5'5@44}53515͠c5544I5bS5J54&\4t5552Z5UD5505|5'45CO5\436,554Wi5@C5 5Fv5$T5Or52F5<55;[5U4S5ݎi5g&5V4n444&Nx5 Y49n5F:5m4: 5e6544UI4U3J24_4e"5J4x}4=4434 5uP4ˊ4k4h/2\.d$4_$4I46!6 38T11}k.Q4F84T`T44ُ3vY 4W{2{e43y4 = 5 4L4ca3E4k4Bn3'K4 g9xh&|3D4jY4'4++ ȧ$@3IaIUD4;BR`3b32U6Ҵ! 2D" mB4R4*4GC5\54r4~43&4L45*^4#5V?4vg4⦆4p4<4s:4U4.84q44054*m4 =4M24Ӝs4-m33Ԝ4V,K4Xo3343zs2sg40҆44~o2D4ʳ3,4n3335h4Cȳ߯ҳ||4 4 $'ݳZO3]3Z~M43 4w4fGH 7]Y Kδ_25f,FZJ w_]s* Gbk,/zߙ p[b7DϩG̥ʴeQu޴/L4/ʑ;ih iG)ͫE3-KXW´6 ò-FcZwTvHe";\6 A ͂4Zyksf3,9Ƴyi&1K3ٓ4E.h33p42>4z4/3$K4<44>l434"53_4J4º44L4 N4v4W4L70K$4޹4@U4&4M2ei4yT4>w4U 534R4 }5ih35l344^G4\I4O445jh404wu4@!4-3ql44394K (474_4nF4k4g64M 5 4c44L49b44_k4Z5@4,Y44v4434 5N4}4)x4\4p3N 4R5@4Q 5r5jl5]4j3 P:5υ4DV47w4l3m 4@4v4`44{ڡ4J5B25<4JL4YF4i{4}=5lD4F4v&544 4 5.5(5}+544~4~V5=45؍4z*45 {4k5)w4V$5*5|4]4}4Xo4mCC4ҁ4J3U4B4Sz4E44=]4_/4f4k4w2~r4<44l4i55[8554d2 25wh5 40ޥa4A35\ 4+444$4k43545NY4?4X2443 434q444!3ulE44u7l4Uh Γ4]٦u4)fF4l4 I?244]Q4s44,454Qٱ3#327p4f 4,3Yek4~%<߮t4U'4tأ3jW4 4:13_'hγ23!2u494*#Z4XS4t 4 4=3HA4`5O345uK,5D4 4Ş4~k4.4v4sZ4P4u$45՝4y44 i4(u4|44w4r5=I5!q75yX;53525w+55H5d?5-5 45-D5X@554Q5!$5{<5R)554]5545:)5*54ؖ"5[I 5}$54=4 V42;4r2^4o4a"@|4m154)04'4e{C4*4ϛ2!4T4%(4mDLZ4[aP!4˝EDٱa4Qx36Դ3/ ԴT@̞Op泼*3"294SWea=3UE3Z3_n O4%4ѳ3] SoX3u6444G] 3uY\j*3A4l&_0v޳e3Q2Z3G Ů1 ?s qѴB6@{д:3k΢4e:34NgI)3[R-'ٲ_\4N4 43"2 4y€G44mሴ$-4>"55q@4Րl4O#2f5l54Q575a4Y,4 4j4; 40ٴ4$5=4jz5m`4k25q4)4@4-4] 4<5pa41633 y4U }4Kh341,4M4)z4)3~N4$rt4^3Z~4`b 44D4:30 3e X4ҳ@:44CT4u4l43?43ٸV1Y0y02yJ4V}xM33N3˳ŏ5cW4tײ&e}ч۳R C['?靴Cմ8n@ +j$y̹F~I.|y]%xA޴lf~1&{X? ~;MGٳxM\@> hb#ߧh;JմF SKɓᴫG![JCFV7ܺq\u&4ȲԴN`𽙴o"$?XM.(W{wC2GIU3Oz^DX7 =شZ׳|ϴGrڴx 3BUIM+(\J"]\δ!ԴN1Hy鴴R|m` ҤĴqz2\puE3@$ 8^^9d6;b$)3OHu4=4zݑ)YZҴ?4U*3gfvtճH+4 \%ɃU*}C0Y~sY83X'гKW23Q40MӴl^дx$4)дDH Ci4;4ąw?>34G6 Vs0\H~voôi&a9΍I[3?kjD4_Qk?~ɳ:ȳȻ4c3(߭2O޳?Z8撴o=HM Gd1]u4J4mn3l4ㄴ=4f3}J'j3ZMCG 44ݫH}4L21֞YA3%3^B)sGAhmOn3P̳)e3YF?M: cӴ}#4". <&U4ȴ赤൴#l8w3Ȱ083yTjTJ4@h*4߬ g9Br63:Y*UKTMփsd\"h Wbn)o].y4/[\dp2m ʲ@mY3vd4Tn4*6ʴ1Y:u׸ʳF4;!ɴgz1dOv 3Q*Zf~ kO^Ѵxz1|临Y{$Ӎa]qtq򨩴"ش(̴TfN@״o 0^(W6J*|wcwnś>~´G%긴E*NJ3W4jjV24i,],´"U4Q3Q4g8ܳ'#_4h _h3#j3g3*q:4X3U4B3!^FbV9Ԥu!VH( k:f"NŒ ڏ)+!´raz аҳeįf{REVi$#Eô)CNu3Z3ǞX>Vhб91YҴTE:6? )0Ѹ0fu53U"w$oFϦ_샴2S~k T^4\(SK 23> 4aW+1[s;t]YvnlٴTiXV4в{®dxtĴy^pԴ* 2Tﯴ۳A/הּ*Qȴ/Tf OVPŴ건1 jiy@"w ( 贽Gl$3/CKq3tl|]y3d63h|鄴΂˴xӴ;k4rAn4|3'$:Z3e{ݳ">:Bҳ,ݲZ$s:ӴKִQ&R9^j:̴뷳5ptMZ6CRW|-g7д=*3Uʳ;4G$44tp1v$4Q;4>#484I4jM4߷ճ%5Vfƾ4L˅3Lnr4Q!'4ֳXZdž.n4ImҴw>6vժ G^Rt4dVJM]4y%MkדSfN4rش68УqaMxa[]=PJĴHɴM"H#.U)3{=)0WijpPʲ>7UQFe=ELsҵG*ccTka$ UHD!JR:n³ ,аC[賚!h @֟tl耊 xH%Q ؐ4pE1̳&a!4vH4a>,4pPPִ=4 47*p{`N"2'4}4ه4nv!4 2;"2T743'+r4!4if3Y454~ȳv5Q453O4KÁ4E458-554058[55;5.354m4(w64~ 5e9&555L@4Gt3x4P5a53_V3444=35855=5AA5W44|423b4Vp4Mc4 544;4aU5~{4*455I45fX54}L5x4?4L45*V4iR545254E44Ai5 4&4{44҄s353 *4ul5ߔ4p4%q 5T4w4@444+)5z4E45547T5:;5K.54W05F5!5 5p5\5V4>54E!5I5R~55c58"54V55_4VG5b55\m5g5w?#5L5Z58N4\c5,25E4595U'5,4A5tL5035h|5P55P5}w5G5HM5oZ5}N5m:57D55K545@K5c5+AP5!5TD5:55%.55vl57`5k.5h555ߦ5,'>5Eo5Ɣ5;e5oO5x5o5b[5>555I4!45C567n5H)/5!L5yB5{5[@55V/5O5WE545{\5Q4G4^'5@5o5N58;)5ӭ5١4E5"5f5 45w55u44;DL5W4*4A4<1d424T5%U4܅451F%4i4L4¯55z5Z5 b495U4J14tL4`5!4S4,5S5s[4q_54 85:`4$5@M4C2M5jZ4_495` O5[4=6L44144.W3*"5H4{rC4ו4fe455i4w:3iD%55ԗ4z4544545`54U5 44Y05f45`5!B5 ~5 5l=45ߚ444?5y4 g425aa34G44;5s:5L45I4k+4=55+4F4/5>%5Q;5'o5S$5cK4Wo5[d55B514k544 5z=5 4:4}H4=J35ri4+I45K4G44R24_{4(4M\U4Ɛ454#443鳟3E vligJ3h43V+45"94jC԰XdN3$ekqZOz0d082T}і/oh󩴍|v֭jZu!մ>HP䴺6@\"_x f[3Hٴၭ+坷3y)%542lgY˴&<ߴ.,[oBJߴdHo<4mS㛴Ҵ*w-軴$mM斴XSVWɴmBaٳw PSմGUIѳ%EK]NﲴB$.4ٴ:8Ŵ=%*aZ Ί*,p£&^!Ӵ}Z.{!ٳ/N@!Ƴp54nJEA="-ߴ]xѳx3|KRҩQG@`x (^˴d'<GA`Jsɴz9Դ#ڌ_G=!Pl̝)`d$V4S\1.j-"[ N̴aƴ$ p!p洛ɠ3uqN4ۈHO`0M`} Ll5l3sߴą醴x*Vi%¦?Y񴹳´%ld1ԗLǴ]'ᴦ;~YxT=>c1T봀-j{:BP `ִPԴOش`$HԴF*+2Z?c 6[3:-L:qg 1Qyw<ݴ._@R$剳 Fs?T]|-ePfʛ3}Nm6ƴ]ҳ@Fe4tm8b:D3 7r})רôUԴPYJg%)ƴpӳ>&ӳHഄ4w (D賊봛˴\l]E4=N3p6No@$ ,o{K gPzaSe.E{ѴY q^XWHXG{!2\(;>Z^1v{mѴ 0<)KoBu@*4[W6u3R}ݴC*;v³ҍɴ=&4U[^@2Y\38+8ٳzz/#۴d2>ZŲaP*[2.2:4!>2mw33tBӴ۔3f*a$[3 2cWC4}47C.44~43m455+4e2/jvQ%3>4ǩ&"s3jaz}44$2V4d uT΋D򰴇oy#SfϳӴ,1cԴ+DR! ȫ2$41!4r~Y^o4t@3d2_ڇξ~7mAOvRDm833*ڴഃ|{n3ب_d4i:ҳ6P1۸&ȿ13 204e4M1}4Z 4l+4|&54|@3-4xӣԴ4Lۨ333@4V;384C/wi4؅3X4c+.4 2i37i32|;4Raϳ7B3iճN(5e32y4V4}z44sW4( 5i~'C5"5xu;5g4> 5y,{4%4}V3`4m3s4O;5⎴43E544Q944SP5#)4 |5/#545 @5i4*p 5|4 =58445ji44x545N44ki4֔44<4543(0 1!52I45̐4.5?33X4f5h45584 5$!5׎65 ~a.5 5 55G4n34ɸ3î'4Q2X73= *4n4u45"wz4{q3>4|(3ί}3Ț4Q4Fe4``4s0DY265@x403 4ʔ4 Za 8-2F2)5w 3V4J4;4Y35"EjJ4dCҳ E1Y44143 KQ46L53K؃1-i43[:43;343'G3Hm4?'44 = 4eL=+42W3W;4OQ\{F4@4863|:J4hd3B4~Vp{45J4pB34L4Q4"4~w4a5=4*g4&5oTK3!n>5K344}4 2U44'54wY4=5v`4555քG4Xx5ҐU424.%4y4FC4 4U444QM44%44J\35i4pJ5 )3H4º244|V4e4O4/434:3-5Pی4*-44QX4dC424u4쏴b4a)3˖b W44:43yh3a/33Kꪲk3&拴4J3 6J4 3N?76EnI ]=c(2"X4<73L3l13XA4:'C O3g߱n"4@j=I~[4$ӴCǴ޴*66OIeO<:K7F3\053ő Fx`()1^ִIj[uϳ=2[1)an%C 3ú.4Qe4"$3.V1~&j3]3N#ӳ'>#Ch 53BR4-@дN4"w4}]0)v 4#YUf]91+(L´7?Qu(.d-7g!,ϴLǴg3(k8ܴP%ش&H!v91Y&!Fd4s4I14A2\3! 4uo4c.2sZצ 43;31:2 5#ǖ31%2>29軳o2$4P4<4˨4]5E|N4 4h_³;C4aX4e*|POn36A.4,/45Ӂ3 t3S33 `4c3! 4o4ŵv*3Fs3,T4nZѧ3ֳa0ug4ᄡKWn@n ʕ5c֎6';P?WdD3?<52&ִtMm9-,鳴ASlKCn۴Gf&W4AԳE4)zԴkYlʹ զ3LK4SuybôhᴄY<1gw<SRϴ bFM6vU7δuo!_ev:X+2'QiwLp,; Jsᴔ 13  ĭ0Bb+]  ,6 12}14 2e003) Vj2xT;54څ'DɴJ;1Tv r5 Q@1ægBb/<4OՍm<?mG ʹwexG2ٴ0Cm }$Eku$=4iE5 b~8cGô"bzw m3B nFC:Wnִ]մ=<%!Ӵy% Gشi h崼͡#Wu#*˴z۴ =鴚ª@]@-մɀHzͶ <\Q3ZwGꃴ$<y33<0\q}\ɷE~ 4д溴J](gT+ 4+)qݴ>W9ٲN^ƾ8:Z&o3|)2a{JFxQ0 g c0{( -303Dp+Kȴ. δ\ഥ̶:KgB4[VWe2Wœ.ゴD ϴzqgBm"޴ vaҙrƴS?ϴ7,0%p2e9w1j[8S۴ô$]r0_9gJZo?gDKa3'k`y K"Ŵ`䴙%մf x8[D@o(=ִD贽WAظĴܪڴ:k&Ĵ-̴f*N>c3~1 43 PG>}^.۴ճ:ٴٳ鴳 ҳ:9$9]/Geal33a>4䳏'1(04N'4FǴU43-46!F3 w4 hӲ":W)-1;ʹ,t4v3A4 }3B+Y 5xQ43&< 4^a44bȳZ4^43<4.3=4+Q_4(484ڕ43o)94:43f4Ź3"-4K 4ʹ3A٫U%3G4va 4mǴM3~573aL2j49m\|4Qc4h43U4@4m44a粯KT3|wN52ʌ4=4ia43M#48z2,46#3C2a34\4 3z94=ke0p<3444[VE4:4E44%X404t4!4=3E4p(4O(4ٲųm^55j474 5(5P3m4k44B44244j\3"44~gJ33b2"t4o߳d4 5g_4T24&56v44rfu4B-~4v_4}؉4R5W4+4v44i5):4R(!5W3ϭ44O,44<3i4$L4b44Z4=5434ף4v5T454'<5F4?414H X, 44^\2r4r ѺxHC4%4\4o4(t44@4@43(4'`4ǖ4qYS3Q4 G34x4<5-4!454h&54 55^44Z484Z\5D4G14o4c5|44"454]3jJ4LZ4`k3w444e4k1ƳS"~4'i4eJ4"4414t\55J54O;54+46K585(5W40455r53 5U44̰5r945+4 _4u3e4f54º 5@5{455v44)F334>5t4qB5F4'3N4*n44"?4 5-5KU3 54;4$4^2W4L04?H3d83S ׉2Fzl4o3$ͳ33m;vɲwE\4V2"2YϓᐴF:¢;Ts[3>BOLZ\L43Xr4:i333eE_3+3G5]84c4S4hЂ4><3X27c4 ^X#363KϲE1423$4_Hh~3ok4SFj,/2 |Yct_{>3Q᯳癴E{˳YcfSǺςϴ7Q]*iചسost42295a3峹/2[B93"3n t4i3WŊ4@t솒3$x4CC404o3ڙ|4`4P3&42R4}F.?4e3`4gtı5k445b34T44z4j,4&58"4l" 4%H4]{40f3zC 4ÿR4NC4AK4z323O4(ډ%4"144!45O~d4Ž3'6.1Ye4IM_ϴ,U23g.3Q/g?412!)v42+4hS4Nc7%3e4\4.س83V%2:43o{* Mm)س^+óih!R 23Nn3/lB4^8fpe3d3|3d5pm2 435-,3Kڲ'F4YxwO6itK!5Z]3Vm=RH2>hus)H4N93\䴉 %֩!2شd˴xγ ?_۲L̴޴0fp$'v $[{ Pߕgn c .)Ep6D wR c ôؔj괬[ n3ڞ DgpǣִXlRXkX.?N+b.D4N73Wg"3fW)4ߴ U$b3#Nδi6mbv3д_ w+3 >h ǒ^R<4M'(+n&]423:3W4/4'2 ez,3VF4X4{w4@4c4 ܂4wx43z4 p3~4ɳ03Lz4ې4)w+j4A4}3G4`e3W4pG42YL:4;* 4Q94Vy\%.10 p{4"fY83 3Z2FM~SQa03kh 4oD` 3s'קO3>3^촻4mEm4mG45534 5p343p(^4e4lm4|Pu44d#4㙦 3s4awo3ʈz4#̳UL@CdznE0539]4O괴VڜaIC󴔅v#ad/a2K4ѝT)Դ˚r1l#/8㴠uDkGEV=I۴@ [2O˴hj d;鴘\R &dÿ3e͹IT"z04˧ f^a:XZ3#q24Tk4ѐ24B-Lճ93f|&Iq|᜛#ɔ3̾4}\E9*l5e3Ǟ33G4!ڀ4*3pYCM-4rae|A*˝Q3t(yL*w13&37&4VV4$4$394Z3\4F?44ܯ4 4/w44L4."5!5T4U-54k4;44iSu4MW4*M?4Pޥ4~4b41 n3V\ Ŵ03z3G4r3Vf3keѳt4&4]4BT&2(4$33wyl3jӳ[0!<vZFHܴJe1)g/`y贩T32K`}x噳;ôt3\ôuR4gK3C[:6O2+4&0N#h4 T:4?]o3'  62p^3 !4xP64'=yJ;cn,P074_2ځ2FC}K2.ily4 4[q!5A鲲d44+4I045m~ 5c!4X5s44h3oe4514W44EK4Rc4`4tI4%454Ʈ"4f54G5\%44WR434q4T4ϊ\4e43|ݖ4V"34ɡ4bҹ4Ч3D44954b]47iL4҇/Mo!2145H3g4Åȉ +hq4x42{=34n)/^3}4E3Q3x4;=4w4'f{J4զ4[@4b3R332S3lnw3T4v4ㅂ3B3~j3*41-x4ԘQozRI'8Dzc׳;.Yf=4ą4]9cW O32Pr383ʱ􉴷ylI4ٳnޮ4cpq[3*m^3"߳Q842!3F 4G04Ca443mr3bb33323X۽2}3W8CZPA3124 K44=2 44̴44cHL3644L[34+|1G3)4hv3T3a-4Sx~4k-4Ga3}#A3dB4c󴈽^/3<4k4J3"4̲#N?43p3(Y4e3"4b.44-4r[4M4| {4,v55%4/4Tu4+*Y4ԓ3_34B4h4 5ǁ44oe4&4: 4U4yW5U)4Ch4@h4=4ݰ4*58 5F5'5]4l4/4c5]4x 4e4>u544x4b3*2ɡ4ōL334j3f0^4$04ݵn4X"D46Z؋4{K3~4 444 5(4{'3Q4J 52404-.4/4ۨ4M444-?5C4 9 5F4&444 4{'5(d3`4ڬ]546444*"4 5N4-4Ic3 5p5] 43:4j]44 6494t2ͭ5\46׆4K4-}-5#`4454@G5[14gqc4+574_44444 5h4Yĭ4X54i444pZ45[5eI45=5M4q54 4&4ZF4qg4V߰4}4wH44v4޳.4Y4334''K4/B3$4T1d4W4:XJ4'c44h74r!34^4W63ojrֳCdz،4m3e44Mm4.4^x 4<4#x4ܠ4A4>3h43MY4໲304qu^2eF4]4Ȏ4i{44R~4n]@49 Gi2}4͗45Q4v4Di44Q 㧟4f3>34FP4b/54+h3,W4ٺ4?dZ!4u4EJ2y37ME |4y)3\4t 41 4[4q 53e=4+|4c4c4 3ǡ4 c 4e33at3C4`4LeM44)4ыD ʷ|bXt333'S;c4Qt?P˳3_H3^] &J2OGjG9l3[36(v2Gr44'}3IS4$354UX[3$4jC2`3ۼ4?3Btq44l4*5o!,2Q"043i34)/3Ȯ32d4$r3ִ0FA4_2Z3N4 4a4<%4֏"(42a.3ZX=Q-2p3a4oN44:4u\q54h]2P?542"Z2{3eN%4ؖ4\4-'43\4% 4=2b-O4:B4#94?4D3lJ4~0d_j1Ç4j3(S1IA5y Գ&3SA33x43i#50kc3ߒ4g tkC4-n4;M2/28( 5a4R]4;RD5Jyj|4f3HM`O5I 3G/3~4)4g4 4t]4Lh3P~ 4\Q4O /3/4V<4,3K2n:,[X<3;h4@Xz3n~35<*3޲< 4Fw4 *41!FN44T4#4sDSp2^3ݯ4,3k)4 v41MC4靲4]?=42sB4]44s#4pVD465i.43`4Q4z)i~4ݦ4Rф44444 54L4+!3͉34^$4V4G r4@B4Ӱ5.4qs42̬2>44doq3u{4"fq?34[!I43[%4<44;r4f44Ư{4>4qmU3'ە3(4B4P'~i>|EMp@ݳ.~ 󴴑Q2ωbٲLE+*qt6H.B޵."k,yC0Ǘ^9$A|A% | RSn8ӴD?cWH63+oZBn 5lif69Tʡ1wjKѳU7ִv(ʹKȴٚ/uDᴯ(IC9X,%ʴ/O=tɴn㿴lrަz?+մ~3"탣GѴxMM349I%4hOݢԳ["4 O3QG4Q4->4jř14Ys2Rb1Q!a@τ43}Ql4el²;3/4;5F41~C473'?4F4!5hl4f(4D5َ5o3_`4m3 5T4F45z2F3l4Gt4;K3\d.4 4ѓ3w2=4-4&2{ږm22nE3C" z*9,4= #3ԉ4zO(0ze2J93+z33h (33-B[ÓԴ l9v$ɴz̴I Ҋ}ߴyȴb /O21+ʳyയrnŴN=󴷣IJSXhdT@(贮R|ŀDqT\ش^&p\oNQM3<]5U54T"-&++_*0RdG I r0+CM;T}*\oq2Ǵ%bÐ{鴹zz2:=Ń'6F4j?HNta?z6ѢG6?32m;!0m泦t*ZL3i`Q\Sme43}2&=y4B4~4gŔ4C4M4j(384 3ݷn3ev5r4p4%4x4kF4tI4 4_44G4L43}4844/54τ4oկ4#55ϻ44Fn4M 444/44m4n4BI5h44Vu45%Ÿ4d4q 5k24o44M54Y4AUХ4 33*13(364dz3B=4ڏLtU4a׳_M 00oǥo 34a&3!4nq3-F3Yp3d3ճ3J3Б4f$`ɳZQ4CAXJiWilH ˞Lx3/ŸٴǴB8oO炳g-T3y2"e3 3Ba" m皴 -jSɴFl8Ȏvcհ53~4d*,j πgcߴd3E3W-ﲟN!3 =Y33l#*)߳m1464 )yz4H3d4qe4Z44.5*qH3o5& 5)35}#4«5!94'4r4' 5w3F4]54+4"5O궳3J554H5c44,4*5]4/5c\4\4>5Y540 55Ӫ%5#4L354<5 5c=55524R5r44q4z4 C4V4&144d3)554,4ǧO4.4Ȑ4 k2Y襳<(5B84h;4E45/j45oy4\47t4 34P3O4*(4۞)4%+4Wر4 5F45t4`4B4"%Y4ܐ4 q44e5) fC4v4`24i4y3pܳWBau^)ɣyy x/kD{܌g?5\ T˲$4339U3b3922/414Bn43Så((4+3"*dtV ?=I|Y{~l3hDosVH"4?> "z3|'m4+KѴL4VGs]U341hI4'30'4~ճM2f=v3N"4 0W34i~p3a:Gn4⍨3 41D4f]*4K/Գq47M83y"O4'4ơ4ލ4^44kvf3O4/ 4wb3T4+9Z20/4 p3v(2<414b3 rW4զ4,F"W穳\3%G 4w³滆$SqINǴ%DD#L\ﴆv:4A;׾43 4yY4`4)45t4'@s4z-Fܙ糂92Jt2v9ijAQ4302)Fʹ{:s哴vQPꍳg04Ce2 g@4اnaIb"k;3sCP >2_3J4v`}f(j%1\L={8شN $+P4C 3{eu`\B4]ø1yҳy@$3e2|i|)(6G 9tW면9=Ц봯"-EXFBE곔!r*Ǵu c0.6~ܴa24R ȴw=AӴ[+q# $8LгUTj7\Й}B4 ״JjWyY߻T/nsTΡƈ3_\|%۴jrWw%SjN3a<*괱Z$13aϱBX೑γ/g }v4>ESBqz36(3̀ wN3}pʟmWw-3,Җ>36/q83bV4yֳ^+4=BCSJwF2PL4o1-óI +qG4֭N2xԊOp4Lal|2*5Lh 4_^,ZtF(}1$ʲ{ 2ʴeʴMq2z=д _DгL8b<HZ3ȴ{U Jg0Ĵ0մ6ϴvfѰڴNŴ-״;Z)L+A*3@ө4E,bδk#<,遵yV5Δqksҵ׍=̒M$u5} |hڴUT2ܴkrF ]?f۴k[0|?% w{*BF ƴ"nR;$Pڴ+ŴҙڈF رv|W˥ivSPΏׇ)Ǵ0/*2Ӵdㇴ ʷg3}BTPs4r f4~}(3cI@I *%&44?k\44Mwe4g642?$4"g4344I!424/41م4"53O44Mb׳3t42/̳<4K3 a4׸44s4\q42Mq2 F4!=#jI1|4-4]G4Ob4x4"5_4پ4,,?4B 344U2ȝ94oƉ1rW4c4a4943u4 35[4594נ>2|3ң3l4fr44[R42m4#{4ʰ4d4Bt1b`4ӳ4T[3О4Pȳ!K3Lq4̣34*34CMEO4h4FC53x,43Yyñ/xVum62=34SEr4d,._C3]4;Y^EW3{3(0K) D4M4:4FN;437枞34T3W3_]434?O3@³1-T46@N5a2?33>:3X˳g343.74c4b1(婴4-C2쾐V 35)3sL44B3:4nj4dp4[I3*+3ca1+]495wt4E3n3 ܪѴ45ڈ4l5́4NF434BG4n+34tj5r44MX4(4!4k4 5Ev;4 5\3I<3Z2R34~3 -4e474%/4J4c4o4a3L4N/3* 4F{444{+3lh`4]45\44kפ34G4R3J{4?\4DH43"194nf444K4OM4(dZ45I44x4e4w4۰3ߊ4C5/Y5^3I595v-43Z2a4r4r4ee444>4ųwe/4 4b%3Я*R(3~~4Z&\j13g\3,74Gg14r3|J3dp;4ȳst&ֱ.,RT3pXڳLi߳~1OʼD4$4_5Loֳ4=~_+644GDXfyq2UG{F&43$lIr3o,%s_37|34)H4ڞo;4RV29Ҵ_jV⿺km2>N Q {ȱu1屨, 3w4bct3 3\93DߴFr2| ]ϒV3ai@DVNײ)4>9̼3O†4 ݴ3"ۯ3YJFܴ1Ĵf9=b3, LYE34د \ EV09pw+FӶz33㷳qC8b4s6شСT42,j43fPD3|ʽ:Ŵh,йN-Djl@3M´gzk<e鴶 㒮ȴCHX!Wk)Qu+xln%yP6?vڴJ꾴HW޴;ӴeNô |{48CajH1'DHBɴ SbP`,ڴf´>ҸЗδv%޳zIHC@ `I3˴g0sKS<>I5x ATW)n(3J |22Y3u^=av ЉH246N5#34<64>46!)S4|d44iWȳ|vɳS9Z2C?4֎4=Y34`415Cz 4%v3<4 2 %ӌ3ZU4T4a44w34X4ו4c4e4u|4Y4۬3(5.4v4i5'#4`4l 5߸4H4HU4;4{44®4534ޚ44@20 4] 34 4|j44/W^4@4={]V53%[0i"wG2N41-r4lU?43͊44<͟ƍ82*4ߘ2Ĵ4d443h74aOq䨲ImU2&b>- ˴`?'4qI)[ 1X3 :1o3Vϴו?4w봯F3猎ᓳ4$4ZжX/R4LUYs44C4hwoB-4Ƥ12Z? uѴP4foG83偳ぴ@f84m,4Mpb247(4C3:+2g_44ó;FTE=h| 3844vmZ4x4~Z 4pIJ[Ut34na3y44>b84Q&4N3fd55"4 a4Z3R3P4Lx34W˴4g4L4ZwU4 ;.4@4ݒ4Ŏ44K54E4{,5.]47c4*C45$`n4~4 "5-6484Ϩf45~;54(4(244 j4w4!&F4)4@n3q+4n 5{4MY3`3Ր\'4F 1$3f3ѳWx3cƲY-3n ?~24P4832Pq3!W4a4䳶$4F44yd3&Z4 A2‘34!/4դ3 3 3zN4}=>1yV4q->m2hUسv?߳ѳ3qڴoCSˬ,ƴH3CU`dv  +ش34cfMŵqjj1S0LQgKxM+̴Gmg L4B2+zkr\KCg*,IGTGcEE3f3ŴKbp,M.3GҬ5s44NR4B4mC35P}T54-m4I5m48p5rrB4R 5ap4#4_,34x4v443_85.4;UD5ɽ4(5<(a46ݡ4宅4-4E4z4744ܟk54=5)5-.5q!4K5a4E3[45 42`4e44\4\3#8b4x4`4J354054274(u5c45X5+5HG45u4吅4/% 5> 3S4dr(5&4 5΃4455Z65_4]ɛ4E34i4/4})Q4O$4CH4kY48444k[4V=ҳPL4C  ]3q9!ų#'3tFneB5e}/43!V%3133xoutֳ:|W3{{'C鴕/_x\^4 i',[2\45d3P T³Y doq1cŴմN]" 24wV(76Ŵϋ!@gԩ:{ЍaAݲ>?a03V0*Vi]OS;2 3ݴ}#(<ųx^Q ͳI4O1b441K!4])BcDBG-RН}iR5 X =մ%"ͪy ˴ / Xš EX8_!6'Vh R˼ٗ>7nQV4aw2/شD+,$Ǩo(6-+jy* k_YpRam<K QĶqѴ?ɴ,4*j*-4 Gޘ웲8>V`L32B˴!y1b3c3{񟴽6ʳqZôBTNe T7GnҳB2*4Eb4v3pR4ko883̤>/4:4_Θ542wSմ>3Hд\_4GWPrByдc9?%4g='']^`e*[xs:uD;nZBdZש~R{'΅˻44 OV4ZW/Y3P4𾆴c>Ƈ24F334Þ}-3c"4h 4bo4Ѭ3'%2Ǵ=6!@ I_Me3*(4d\DZK{'ش hW3꣓3p34p @f-O4r4p44Gm4m74m44t4)]4244 4to4f4[44'4 4~5g844.5H,5-55(5SK5QgM43z 4;65!535L5 5<5e'25g5X5:)5?o5ؔ5Y5{55BS5D55~55]W5N5p5"vv55 5ڸx5p^{5@W5 E5HbT5G5!q5_J556pE5dl5{xe55O\5ё5ˉ574{56_535!5Ď5?_5{W5@>M5/55C5h=50,55J5~5>=5+5zQ5^5eu5 dI5-5nd5lC5U5%4Α5p556594oG5),|5R(5M_565Fl5#5&5N}S5ɬ554e5h5m59G75q5,59T5;5+5:F5"55#]5:u5H.550055ux5_5슋5,Z5!5&i5-54r5B5͖'585}q5C]4%Q5e5;A5pi 5<5Ym5B5;55y5@5ԉ5w5454 5DN5IM5 5*5o{5P5ӫ459;5*85h "5444|R4[55B?4^p4_4b544<4ψ#4XUX45Z 4;X3&jmr49<鳲a:43M3t=4Q{#d3I3<1 4D !4J4e4b4ưcĉ4z=733jf4% v=uGpf3Y464:n2owV (}|U"ew>jUcKk-D9l'~J"L"=V0)kw"2%BHT&#aдr0O澳ʴX\f0(%+ {4%π޴~ _a@p¦bnҴ'gxL4w(142´Q}:5RI33]W4WVԳל/kMѴ^2gДJ):ͳP1l,Wg-M6n+'3pR޴?UvQ|}\=!&'`Lu=ʹ,6Z)ܴ&P +k1?9㣆!,F2>pQXP 1QFRÖpQUm2U.+k3_ Ąj 4R(cB+O]Z3hn^ŵa~U5a} %}W#!2's,~gQm+uTXD5Lvҵ⟵O樵'Cn&Ilp-q43EuN4P8g4;r46n15b4ѷ4# 4=~@4ȝ:}4L,3eI"X_=gGO7q33%-y_%h|y2VC³2´w\p+ײ.ׁ-ˣ1 :A4p3;26fE:pl;4A3Ö́Kߴ_p0X2 ifK礴P jϴS:'"@s9K! ?S%i-DP[:M;}N{Q, }۾IbzZ_+"Gf 3BK$C(p_sh}ͳ㳛| 3\29S4j܎'44bjT2m4lF.2L3P2}3-feu%ʱz%kS2TǠ_>EX`444Pv4T 46 4]3r340 4:p4 U4z44(k~~3ugC4Da4HfW:R_LC4Fו4!4w 5S5R`4-5D5G)5温4w+5484P4o½3v5/5564y84"54fUJ4 K4/43x4m 5xAe4*4a5&~4M`:4^4؆4~'4'4:45442 3 ?ss4h3ޛ4^3W4t44P33l3զ34 a3q[4m33g12v0+H4C3K(a4X33~O.5)4eס_4֑'5zV4q4D!4A$5a3 v3.3E4=+3}Ũ43:k4B4)44}43n 65!3R4:44!4~4374v3‘t4H4Prdzr=4\4q2W>&4*C4N۳l44}|)1K(4Q4A45525N55 4D5.5G4zC4(5[ 65I/5 T5-5:~4L 54.Y454n65};5b?5\#5Q5P5c4, 5G5:55X55154G&54j45^4p4?c5za4542464^4xU 4H)27\4vp4”]Q) 5Wϳ4^3w45V3N=)824w43j4d4j҅4GdS44*L;n4R3>2l44S3#C4t3 42[ˇ4дy4F4Kz3b?4}34}H4e44Z43N494'"o4ĴBu4% 544*4P1޳e4tϴ-9~44Ref 2㊅4L_3>#3㱤3-|ƳQ& 4X3:3%3CwZ4 4g A)4z1~424}$25`$81H*a<33j3V-ǴAδJ`y e3^[m3sIK3 S43R:K7ݴN!8BO촶ǸIVȴ393FK4[?vʹTz3 4k=) Ћ3D3t(N4FN4E3t47=4xl4M3شHxa8 ?F4';q}c4ނ3;|4.I4"G4 >p4"Fp3n`%4443\~H474J-4 b3R35431,R 44>s3f1G4T"4(I1wسݴj{l˴lǥ4 Ư?I9o0 P\ɴ镴0T$0gnnnMCXc\?UmT;/|aw>=O)~? UҚifg6knYIn_:@`.%{r0GPNFqcȴFFeFǴep3zBvc<2PǴw% d6 4\,B _SX+'_)w$=wjc TNApsJEoD2Y,fX)&?)f4ˬ7UBW2xX#4N1o ?j\U3$E4J#WAʴHô_Yʹ`F3Q紴3|G\jK2Q3T4QE4Q5(*3ATl4JpT4:G43 36*Q`3kV(32*1Y1Yb~n35b4Z*RSu.`ش>cVh&#cF03H鴱: w3 ⳨<޴:SWٕB߳h3 A$?ȸ0b}N{C hb{F8<K"-(WOk4V'Z5UKaдVCĿ5VJҤʹAF=`$8Y %•@,;GQGn$G12 J|rgH + )rH^hࢦ:B4V3"ʃ4)i3Ew\%3Ԡ\gAϴ9ȀQ3l|3tD4H2+#T3bޜo+4a+Ŵ( {43ww3N4ha+c;398[R|3,4Sg1Yx4 m4"4c(14۽5X3 84<4[4t4}.434N+A4 U 4_ 5?4 )3~^4Y55,H5"4e4g534 4p44 5 3O3tx44Eı>!3HT4x^س}ψu4G42V.:Z3"MB4%}/3nj4XE4v}S"4kʼnԳ3%K4kȳ]i4ʇo4X ⱄJ9n_22 47TF3 O4G`4\%8<34:4oA4h494{3^N1+3&; 4p8344IG2׳54>d|4l^454'IK SL4ғ2m'4>˴\4 )4dij4}Z43B4ҽ44M̳ l4W4@듴2B443 S3( 4H34l%2[nS323.4ij*j\Z4vs3p4g43344r5#5j4h'5-554u 54ݺ5]44A4`4x]d4a`434kF"5ɍ5e;}4:5q[4yq4Ƅ5156{4j5C:!5e[5EO5T4R4m05( 5F5K5jO4ԣw444;B5|5)54a}4?5z 535N54χ4Oy4@5' 5N4i3r4ˈ4kk4y43}3(4`}4e,35T4 4َ4ȗ4Eo3U/4^4c 4G4O>4@4I4+k?4A4t(4s4JW3?4~t4$U44z4+4d55Z44n"4>45+ 5 K4*<5m4574B51\3 34H4 5Nسd4۴R}G(eq4%e3Z3AE44&n}44&43;j4@^i4V4HIJl8442pq&4U4q3)4 M5H&4Ҝ 5fG42 444I84>\p58541I15%-3=344C4n4I405&4Cx+5@05Q54G 5#4A535I5 2Q4U554R5e55&d4f3u5i[5B5|4?54#3 L5QC5v4o4um5O;\5%5Gu5߃K515h˜55h*5"_5Z{5OY4mb5-5i545ů:5Ʌ 53SU5d5@55FS-5+4g 5Z4o5;5)|74Ȭ42/3524b3H/4&Bl)5F/Bs>4b1;24-Ar4n3C4[bҴ44~I4р5U<1(3 4oEQy4 Mr3V=4гg*M83馴*ń3^2픳~3}a4:!?4W 4;44vD;^S螴ٴ"џδ,t A崄I,=BĴLѩpڴu4 4Iub243C 4q`4-4.&4r0&34[ Nk|4hP^Գ4X36 4B~4j3K4Ԥ472o4"(54H5 4e 5w4v!5]br4,4ױ4e tbf5&"53=55r/z4j*5R4K2 52,D4w34z{3;4/4'cG0%4ލ4=305Iy2 45K54~H5U4kvX!4{3zH0>Գ4㔴ݿIiJl@شуմijj3Y9˴6>04r"1337*Qp38btLF4,fF3)r牉04~45ف30޳3E# 5ʧB k0 4ִԞ24ɣ34ԹfɳӻZA E4L^28m!;"PFQ[ oD>4 xèpx)e^~ٴ~3!#@( /´<3Q (` 43Sn4Nj5ch)E/+34`ª4]2JL+j4A߭/5QұNzY`_2~3+粮Ш4=4,1n߳6941E45&3p 4)ʔ3 cLf)Rb44@ݿ3S40.4-|%5umZ3K̕m1/23Pи2b[˳oQ_Nl"4󮹴=>4[4AwX4[+GV3(V.f4/ݫG^7|vSHд`30S׳2_4PǔKʴ3Q| ^% ~w21E4o3i34}gfn,4d=~C4%Ʋ0;<Ӱ4OgQ3_53Nܴ2ˑI8lSrvH%Q2FJM2&I.o?4PJճF,4Z ۴'4dr3 4k;&4Ϟf+3484ֳ4)4H 53/4ä4qU33G15{fm4O42lg3Gv cDj,@ݲe3}49y4eNnNZڳ&3z˴uf.44g4k33l @4zN^kewX4 30ӳ [X4Mgtp:3ܪд 5S48֏'4 B3K3F43!3T$3EhPD3h뢴 N^4q4}DsW\-<3 34'j: &WzFJop´zf-C)?FDɴи,%(#Kw=a۴f تĴ\Qqs b:.4ƴGDr8N˽!27ƈi4"r4j˺ݿ<4}(pK9jV*W³(32 p &ʉp--4 4׳?2-G4Ў /ߤy3+l ,4" 4״uSCӁ53T˴-4ZHٴ{3h4r43OA334բ~ 9ﴒ8񺛴W"?U۱ r'A_ӕw>9yaδ|4K34L5:4s&2524=|0_,4Xt3?ZW^4|4eNtCw44:5>d-g4)%r+H՗Ǵ3q)'~hi4DFL:9#뵵N~ <:ɴ_d穴 aGM}jk;iJHZݴ0 qQa״g=CSIN02LZ7]щm(N&\ޱ j6J'f4&`yTT1^X! 3k/4 81[4Q 5@!q/x23C&;2CS }4334cUkMv 3Y4A?;@44\3ꀇ2δ/\+щ  ꫳ!yN4WpU0\&i3h4&44QȜ4A5#54:4*544(9K4 "4$T5J5b 4E55 53L57r(5m49O5Ex5M}K3 515Y3% 5Գ$5~5(44z75<4FF:w4U 5mW3 a4B1f|34Vɳl364Wwb4]ʲ 5ŴB04+46-4 S44-2&&2:<%̴N538&fQ˴=N4ˊX$3C4332\~30RM/˴ 3Q#sj&$-2Z>44L!54^53z4? 45|4A4<(5:4q4DT3N{1q3X03_=;4Ւ}ִgf ÃO3QXǴ5x+48#޴;*Ǵ\ٴ^Xt<:JY>/ CxLt>rab'0?u5wI?D^މ -zmM4{#B2[I!f_2ݥJ~ҙݴ#974==`”P23 63-#uUڲ^Dl~jy_A'xkG!jմ,6o3u=hx=4JJk)]5f3LC14[eܴ!aeY$r>7$5.U⬴ч Y}w2 0\n eC2\i=5M溴)Z"=uI4zHx331 ~kO3.(}# D`|uaOWNN mi/M|'eMa455Ѷ5;"}5ʎ3:d5&|% 5aL4lK#D4뀥y5]+D4a(!4V>Tp\645C_'.pX:{ 'tsM:4lL/HӴeH 4S |)=#Fgȴx dm6ÄVфuU4ta4  2\<1Rw1c 7O8)4:EŴS73Z1423WCѿk0+153;8z㰳$_3 fr; 5|E5 H%_43Qt>3s4U9 2ճ/Mq3xJʴԟ4;c49m4 =4l"uܱ@5jyH@,n4942Q2MB4/D|1d3L4^oMGq4 a\45o5)J8!6x3 4@ "p6)汳4GVW4%f4>t4'T42{uCű4]44ѴG4843;w4%5baA4eRC55f5P3ֲ@05l3Iвo 5k4̺4AIH 3W95c64ܳJ5I4JU 4&n,4a|51&>5U8454D5_j 5:ٗ3d45fL54G4!?5lЅ5P5-Y515O}-5X4J=H5j^5G4nT5*5ԯ3H5855O55#5ݝ5*525-5}5R5 5}5n555rۏ5L5=5D5F5:5$5f5t557B5\5G55M5ӟ5C5<450=5n5I445@w54o5<5h4ꜜ5m15t$5ڊ5c5W5ѐl5b5.5;35O4)Q4ܥ505V5/V5QH55m5y5‡5s5t55o5N5 E5va5;5M!5524.*5#ۿ5,5(5V4џa55>$5,5$G5r@957O5ia5355L5*4g|F5yr5R/545W_5'55W5G5>4`565*i4V5-@5G44w4S4Գtp4T5|4cR-5 {4T 42"5*z4(5ۣճe'4W43?n4a3/?A5I5u2p 4(4,5CV3X$I4Au%4Vk15~4Z2:943e45r4v!Y%F9bCz]?WP3ԕ343:4M^ܴD/4 >+д84H˴QNU4j;˰3P ͳ1Ϫ\4<ִuq4Y4Us34T4J"1&wJҩs \YrP5;48O 54B3je4^[<4c4-hd*4ز8Z42\#֘4R4964 5-4}4d\4:`ᚳzP84ʃ3#n)N4 _$=3y}QU4B 5Ʋ$3[4gy3:4745a_5E/5'#4W>g554H!4G5z+4ۨ7s4$4Q54 4375p=ba44 B@4#75U2ִ煉0 ݏ3 n4մ@5e(5ҙO[4$LԴ}O5XF40F4Ӵ?|Eal4'LȲ y2?o3h4.xhdžuJK437bېXt4 Q*qv3G5I³A{3pD3w崘4W4[sj4լOTg54*d vZ{m.f:0uyJiմZ)34?=wϾ0509foE j#3sϴS!nH4Ӡzp9I5z`~2 `83.1fM'ῲc'b? JQMS`3pZ [BBIŴl4Nn"FEbQ[T >]5촦 r>4w4T5B;x5`Chx4]&4x\iEk4ROcq^64D4n@5+4ID4:4zزq5)[[T5La45;#4h5*4-r4s3M34 14 R4ϣ1 z2o{3C4\˴g4;4[%)44O4Ӵ™V5^4>uE#4<54<("gxH 4`D^3(k{M4f<4M)}4X.9m#24lݴzLQڴI4 NQt$/ ݍL eUي'.̳5?!5 ܴj˒YL+im /& )74:Կ ʳʺ3^`N$c4d7״%켵l?ߴQBg)(εnIj4\0Ĵٞ95õb$4!o@ W4Ⱦb&tQp4$2/P74a55}@2rH 㴓vx41ʹjU4۟3T4F43 Q$,δo4>N?pE0ww2 :Xm) 3^m4Q㳑d8*@554`1e4K[5@Q.3d3 ^5^JGWOOĴF;4b u9͏5޵34*H5+!Iib4܏״ 4[c4K^4"i?5go贂ғ4-6^XK5e}ׅ3-4l;4 45v75,5+{_4!5+hK555` 5PQ4hM4Xc5%t&4u1P-4*,5Pp5643f344Ug]3©3$4 ߳&is5ݴd l4˖Hѳs3W`3563Z44v4g5F& 4{m_56S3U455g34=83e+ߴc4oR4p]v4Q5-4P 15TH-$4Lu4 O4.3])4‡h5ʹv}k44kP@34_jS=5+55:-5֮&4)4p%y?4.58~ 4 ͺY5G4}f$b;4!&6 4I'5T.5 40wwA56 47574!~n5D؄5525'f545QJ533lo5&5 4l5115>953i&56@515Mm5O554[4n4f˴a85 E5t435$4\05Z54޾/ne5UJ5yN3V5X44?5 4_4 25Z4R+5Y5f,.O5l_5u04/5z5J'*53=4)3R;0505g54w.s4H[4_}443U.4ƅ5?^5X5*4 5G'z5-t4ʿ4N(r5a;4J`ߴIS5s~4V$Y 5S5~KI44+:5.4B.3'53 5p5$OZԤ51U5+5ה5sv543Ze15N5'45w5Y4ľ4B"4M[5Y34g5L3B445m2L295ľ4&'5$5qIv45j]fo5g5,+457W4Rg΋53`054лôG`4Z54 " 443u5ʅ5L4ٳm5[x5t4qk5h87*4525U<-*5,45) 4Yɉb9>gx4t3 5ʢ&275񨳷l W5G#4ͳ}kcL4-A4q>`ؠG4m)4T5^~̴4hW 45C^o$l04洷MHY2%ژց44:S4ӵqR95Vp=Ŵщj-H>ӹg!6I̴Z{؜ѱ';J ֞Q^YxATv3@aYi&.*4-8͵y/ 2 ew+c 1 nMϰζOCiPN\{ 53񝵣{X] 5F5S ̴+='2_2UqCO~3} oճd4~mMvb/!X74v1ӴUA=orV^ǗË4QNA|51bS15,E8G#G3t4e 3񣀴K|4 g ߴu-!nv"l䴞7 ^6|qA(*"3@QULj@4l{;h=aT̴$4dǵMh2;F_ag5z5[5555 c4]5J5"5U5E5B5655c55f5i5Af4&5t.65%25٘,5{"_36k5 &55T4)J5m5H4ʫ3N5957U5Ie5Y2p,5Z4mGOz(505HR6'ރ3(iu574!^* 45252N|F5L?5-.wX 5;5a4jl5$4%65ؔ4ʢ5i5$/5 75>V`4?G5U4J5fƋ54"25,4UO4(b5(3( 5)5yS5,5l43I5J44XE 4ip0‹4p5y|5q5`G5;5ަ5i5% |4KjR55s ,5Xu5R֊4k553t O6Lҵ4)5E659C3N5ߊ4i·4]i9<4L54zx65S34W3j4O5&aKu4dP4е 5xje2vRߴW.vKb3h5fv5 5ڼ'$ 53912 }JqG35-L޵#5/5݉MT4g44 4U5 .i 5Ջ6?e֛5<35M]g4Eg54$P5L5Pq55gn5 6`W:4tw6Z32އ4d47]+56"4C 3D5U4dY5BU 5"5a5w9״x5@5}d55l\D45X24Q4}40LY564Q=vZ05H76[J5\4*T[5xZ3̆m4#]5#Km4B#3';$c`[\53?85+*u9bl{[3$猵pP4*425t#M3'n IB5FTa5(#K4m5uԴZX35$X#B5h4}I$h5A4;;5!3R5!e5 ٴ"4R4aV#ଵ<;4y4$4<5!ײ?5<,4׭lG44ܚuLT47h0(3*48ⵌGutV⏵λBFTYε[4qzVL)35u.5+:)D;J5'03_5dc'4`s]!Fo5Ƴs\.548}0,5g94g02iDF5B4H}5Uh5!D۵RLA6w8"5决sصW4{3^niR')4I2J.E4DF˴A3YBV gDE{5gtM&4\2(b4u6,3D4hQ4aZT~Y36ٴ 闵)eDZP6A,-ŵ[ϳ=J蔵aҵ1"9 5=ݺm܀D 2E|]VL=%Ne'x~?,L\ ++ ŵQ 1bX1| \*N2fv޵Fڶڒrv*/>K[̻9;fŴ֢ıK4[jN؀?2kδ:͓4萫4- aC45FV4z<ֵ{͓5 +oLP `5w"'5&3KP3&,K4AQE;=&]+/0M4 925 S:ŵ ɜnݓ4dn0 فZ 54%x E4*5US4h.]5VPiQ4j35C۵.Ͷ5Y5&}5UյF5~-#?o΋54gR 5[c0575۵z 2Ew 6L445@5<5y55 55ɉ5r_5˯ʴ5ɗ5fB5õ05>5Xc3sV5L33 5 ʈ405OG55j5%w5λ4%1'5M0z15i5&`>52&sճ-5~5zM 5i5Q4r^n-5*4l3)T4U y5n-0!4t *u5$5[*r5c5D6:5(6/}4س550nȪ3o5qj{I5v4,[?5Pp4"4n56 34x4P5A44]4t53hm1U0 6ժ5455g3^_5Tu4UΌ5NeB54*W435mY5Q5?ӳp55Н54X5[?5_D396{_,L3ƽ5+4R55r2ooA5<5-Ip4{:5iy%3 M6dq5 65S(4`5 5g\$5be4Pm5h54#-D5'`c5T J5?4=U4´5ͻ:@5;4`OM45 5w#22Z/5|942[5_ɵn@'69òG^dst *ʵ.T5(OcXu-Xou5aZ};5cɅ4Rb4 ['U 74V+c|s̵n7^ 6 cQ&h \N ή4U#5wWF5!Zf4Qc(pej5agH:6n赚'PFG64}4#3>4$X5ijFl5s465s5ˋ&m%6C5Y/586wS9{:6L15#6]56"2Y56_>'X4;X6C5 6X, 56~Ц5QTl6Vli&6 5jJ936 5,6 4NGƵoa46!6 P׵#55!M´f56'3 6GB޵H5բ5Tz5i؝b6m 5Z06ٿŵW6u5/5NPL"ܴߟ5g2H6/Ч H5 +5mŴM5$6b`5-E>5K5N59 ؋ 6(G5~4'6|5{]5~%F5IjA4tlƵ𶲵i6a6y6,e4}ұk65q>6 6(\ؙ%U6RD5@6hL쵅(9693p5E66q;6\4k[5a26⴦545Qk6 2΋1"6'6Af4?75е]&6̙57A5G5 5R*b5r=6q!6A54-646P63S155>~6 6Q26t4-@653 6 656i586U$56k4A5|6[6=~445mJ6)γbS5<4M6&elAj6L*z6 5O5k5J"566ـ5D5965d6#WRX55 664׉6Ⱦ+5]&6|4RNC45`5a6Ilo!6 =6ow f7+Z̶/6P|4jV6hеZ6ٵ+k5M2%6r5F w6\#q50}538M456O5h 6iJn 5h{5rt6a'5%~56d654RJ5ũ6|_&'5Sq4HX5Թf/6q#ξ5[ʩS/6uҴ G.cR25[]Ewo 6Yy6}'y"5A0 6J5)xZ2ݤ{%"6W}6N'5 [.5w*6l,=$*V5;5@@(.6\=55ĵ+6EI4b6*49 b4oдpB6} '6vA5bhs5kQ̊5>K05,tS51K6Kյ50>5L 6G<6eq5 y-6?u5Ҳ5c5 6E"`6.476SE6m65^6^c4 J65i0S6F ^55 5{6!6f6t5No55g8 24խ5s̵F6 5%6ϥ6O=k6!=4E'CN5wWR!53Yu5Kd#854z׳5|gWhD64*%6E[˴F 5!5쫶U(6uYć]A6e3ö5D ܵrW6Vde5v5 ֏G50}䱴n516Ƕ95cǵY|v3qY #4/5M6TQ5H"η6$h6 6P# 7DdO6VE6AU5s57ƶd6 öi6 737K¶6sAs65Q44X5G6e~6h$7OY*q75#lA6-W6ƞ*Br5𴶆46 7BN&77%L̩7*966 \)< 6έo6 s7rh7h/7Oy7H7{ s7Wkp7bg6bǞMp|}7tf7?7R7kt7Xs6nȈTG6p 9G7ݰh7ط7y7U٬7ЀK.7\o5A6϶7,b,7a7>߷7Wŷp7scl7G ;L-6M6F7E_7*8!7E޴7Tp7WUpc{hk7b 7M,7X0(8 #V7g7\Y6h6ߛ7aa8'?t/8538EZ'87 7v6P~-7~t6%83Y84[n8PA868% 875z7!78/v{8Sy8^}_8 k8A%wJ&7 9 7`T Q8o8Ѹ՟8E8y_W8P%N7_r7}Pd8覸88Gڸ48=۸=f858틸$:8Zjfg7WG81˸89@Zf 9NP 8_(ǸMƎ8XR7p7Jr+8.︓S 9&'09JC>9C;)9H {88`;/8F^498)09Tn99冹9m~xF98J}!8ݖQX9 d9)9;йk94ĹϬ9璹\9Z: 8`8 3WJ9Bǹ:cY+:R:B:[Dȶ=:10:+޹7ʃ9bRZ :}`T:8;~N;2ջ6<*f:];s[; OaA;~; Zz;d:2Λ;(;;9;:};cQ;v_;::b:::ˉ;Nȹ&<;U;i; ;[ ;k:'Q:Ȯ:UQɡ2::i"L:;M;}7BлqM6lk)*:׺]L;:e:R΢::o";m~:};jF:8p:=N;;<>:؈:7:I2?:: :ij: 8;Kf;Т:_֊::::ǔ.:*p96:< ;;Aϋ9ފq::/99)92?:90P)躵 ֺz@A1R &?&u6VX_w{CM%O`>|M:_øI;I^D: :8tñ9E*{NVC-9sΞV]:?: +:y:;F;9;D-:co:,;:V::M:*: ;-+st9F9@:I*8ú9vR\E:Z|99yrC9jh: g9C:u::U,ɹK93]JȻ%$]r7qә"")wݹnQ9}-(O' `mE:%,-90Q:!]:'OC: 9 y:8ѧ::b(6l ӹAڶ#ek9t8bC¨9C99~L:O::ݥ9:gF)hչpZ8ܳ:in:K4r7R4@P#9:Jc9s9l:5L:^H:::E:=;K:΂:^gK:B-9P:o:t9.9j㮹{b84YZ:s9 K7YPG8T'߻2`Z83$:fD: (̹O8>K:p8 9B: `9hS9?::,R:Mj拨@*hOF8+~81˨&](p: :{l_78_9@A~عu=YT*SͤJ=D;Һ^,Tz *EM8&UȺN.,Y KZwu_wR/>:i:S}PP=SB>|ºj:J;ɳg;Q;b=;գ:'9V |74zǸV9H:l::.::!uA6-vU˹#|ߖ9 gʂ7{9ǻ3xn(87+o:J:9dco7{|:V8:J8IgM:U>:.'P9C C쪺wΐX$)8yPʺRT:u (N_)Fr$p9P:AH:I9X:&:>Q`A8n$k99{p:;5_:Qh9#S:::SC;k; :Of]:kD:l :l9ea9~#8@979 Vn:|8Ks`+ͺJҺ^7۲S:O v_W|8ιS7)O:9<::M9C˹¿؁ "&15ȹϞ9:&8:7_C#9:e9v)8EŨY:zwE:Զ E:Ж9dYy81f9bq9:8dL :WC6:N!:C+9} :D:`:D*!9u`8"'9I9>ӹ-b8-m9pU.u99 n9H9b5j9L:HA*:i:MY: : Q::{:Gs:9֊:\P:zhV:M:9}9ay: J:v:6:90| Ə9.8!4,9˘9858N9He%պS›$/謷ydE@5&$G:һ1: 94R9:W:I: &C9v:X: 7فY|yG#38k9a9HE蠺!iVJ̺ݬںPCF^Bp ѹT*G(9ʼn9C9:59L :HL:N՟ş_lȩ):9w/_η 9z-36+uk6>xU7z1i@1Ac:9e;74g'»c#;0;k2ﷺid9Q:]U=d)9J&::!B<)J$̄$1ݺ&/: :H:ߘ=bOq89#u}-OxgsW:bFXdgºAOlL+ 9b:ifl:5:0 7:::>贈;qӹ Vj90>HzSս_:T:,UE9:l:׽$:9+::-p:+ֺ]::!:[9'9c9.:Ų9]8T\p+rj-¹YظΝ_9<59U*t9_9 9mL:J:^ť:Es:V3::::l%Y:%8:m::|fOs:e~;8:R#̹::Y96-:w:Cl9L&R:k:9:Hp:Nc9MnN;,:0z۹#]=ȹ94}Q8l:2:$.i:w:İ9M: ?ʹ5[:>:Y:q:;{-(:O8si 8pk9}_9KFK89_:s:p:>:\%U9Ǵ;9 +:8ޟ:)(:.m:l::w`kS9uV ЅQڷ<=5:A:#j9g:6:=9ZpQ(Һ؟Y޺ @˺LU*]ۺ}="8lҺ@ml:}9m+:U:<;92:ےC:D:U::8gX|s\[[79=:F:69ڹnBn8 a7#8{R23:<9e&9}: ;L:eg;1% :`Q {\:0:?909Vޞ9̒9~յ:8+ӺcFL^;960ǥ::q:R(::!S);t:9Չ:羟9\ 4;%>Ի:թ: 69s9, ܺȺ!."`+k9Q*j9ú. FѺ692*ƺݹk9oD:ܴ:Ŷ::QSHH:6 ":r__:q9̳9s7Nֹ<98*9B:2:{MW:p;MԶ:<938:n$:f:v:Q%븫΃8}:#8o:=:ǹ*U~:;8ONM:ӯ:R8rbMЀ9a::10:M:0:RZ~:U:l:K7:$3:5+ݹ9e}9f9ڢ,::dc(R:9579: : [Q>S年蝺=9aJ:F\Ɉ.¶9wmRܺ#kźMAnʹ:휈:Ȣ:z#-;`;b;u(;v:."w^9:D99/^:9vo:.;Jme:m:3:*:H;p:&;:1ۧ9370h<%~–D:i9̹4_:{T:#ff!3p7Kq:4:> ;X9;Y:_::74on: g;.N1nO4 <e/#6G Y:::Bs:u:k2:n8=1D94m":+9 l9FS9 9:c\:':2;:E~9:+9,N':}Դt:\:9@ 9Buߒ#:_09U<̹{Hٹ6ڹtFNiۦ;RԺe2e9&p9ɸ#Kyc=>088d!J8;)39: :=:::T:: %;:9:C:>:PW,pƧ9'9$p4p5e S::;x~:( 8ʬxՖͶcg/^:F͝9/MƱA 9x9&9:TA3M`08RQ̷Ѻ04`D9;b9 i պs,:9FS{9F:o99^q9 :}!8w'h7м:7} lS:w:yu:M9i+:]8h9:6:tm:H Ug> :V):R`8P9u 8PD8g$!ú] 9&-9~ŅGK I:Sc:ח?eჺ#򃕺 3 ,B[9w9J󚺉H̹8hѹQ0:v%:*9N8?>YE#9C$9if:::\R:/U:g۹mr(.*e! й=v:AT1l.UR:99Vd9bt9y:,@  [:9ݎ:Fy:;9< 0986:0a:/:9h8ѹv_Gd9d}:R&9ʋ̹B0>vŽx*úqH=:;:eYg8b:5:uܔ:B9$5wkR;J}^֟9 9%nX5::;#;:n:v&;_;w:m::7:ڛ98&&~кte/8(X4]ƺy{t2L#˹I98YFOǹ2.IXRmP9KZ:2:u9$urSri:Ev&7Ym9M9G:C:md*9H:1:Q8Jй%ݺvֺ4}OR?>S4::9ø798d ⷺ?x^^_9Z9 !9_:r:D*9+^"`WP9x99':6W:ıu:h:ؐ:ݖ ;k;$:=91ٚ7hJ9:L::\H8 0ܸ䘲Wɣu:M :w9:;:e90ׄ49ZD 7ĵź*g):(U:H$j` wṤ9`98_:9ψzA:]:li9q:::{#:ކ9wR.S~9Te@06Tڟ9Iʾ?:3:D c]b9J:V:5x9@0848}ַMA96":Na: :6:ɘ::9?:e6:vBE¹,'5~aTʹAغ?s}878<AKG`QlzE!wH΃9)aS͹cyhk,ͺn-Ժ#8N8 W@B&xg:2:8񣹠V3Sg9R9UUP?::b:::5eu:^*:s9n: za:VqL::q:k:c9ys`]:ј:q8@ep_U:Z#:$9>Y'i:[:ܧ"ֺx@8&,WvP$պ ںM &ԬU90*8::_׸q~D޷R 9)M̺:TiٛECd:]$:i:[:E.:-)c:D:899E*:^ : z9+8NйҤ^8ύ9tW: :ӟ9,Dc9r*:8VĹh݄p9<9S:3qX:ٌ9ʑ:9>:4:8ѥ|y48L.D戺!R9 99':M 96 -A'%N2|ɥw¹7ؽ7b}:X;th盺ٹ 3J:E:z::}::P9&`+]=1 9ϹAs9] :*{j7?>F9k-lqBc资39wi~9K9Xc/:^q"gv9Xr8>\::]J:9":58ΜzSG5z{::O:::H$9t9҅<8ɱx #ah?FhDֹ-9G3:t:2b:n:s=: i: b:7C:߸}*:(:J.:19SϹ@dvK?ak窹|:!-:r]o.s9@:b[@,Ԇ UP]W`b-79EAg:D~:~8]YŹ5tWאr9 :}98rEǹ`Fdg'e#{2rP=X8tC9Ј: :%9o0;9xG8( %˹"ືh}˹+:tҹypYRE4rQ:k:g99:'( 8UjK:\B: :98i:J|1Q[̹,N:dQ:;b(:{95P0W 빕HU9E95I0 =9 :?9pιC9ak=ӹ_` ܹV:J":mC K3ڧ9[x9fs:mL95;: 9KP:V-:N]:9j!38: ::69u~%^!Nj89::kW:_e:V8İ8wIs:^(:96-:e:?-b:;99O8 }9:I:RYV: : kΆ 8Fc9_9ІD:u:&Z|4:uL;uK3;98칊})Oh-hm&38k:#:@Tq:C:RĹ$e-}e$w98_*098WG۹$KHn&0o)XǫC9)k9:'C.;=+^.Y,e9:(9o:R:AX:໹R99/ 9uq:N:)L8-3~9 Ǽ9<=99BS3UKK29J9'4 ;;'8vΤ8kFR:Im9a>YQǸE9u*7K GB"s8 !a :);$:l?|fCB!Ijˏ^e"7M10f;n;h+3޺ _EhX9fl789U) ;sYQF;):4%:M.:k1:ܫ~Q:T9.J8 ޹w9۠:06:jP::c<:<':s; AJū9<9=l 9::z:8൷86ތ7ָ F个 ր9ș 90:9rw :Pw9 C8(99&I:g8l#`hYz*%h?{VEV󇵸L98ќù@8z96иͅ98A:b B:9ohI9[o A9i: m~@La;9:f h:i 9|]8^D8wT9i:/:N8979$:@:J:E*9kKj9cN958a:rWP:8,cɹ0﹠7D!=:]:2H9b 8zŸiIc=չ&9}`7i9J:r9ߊs9::ӄ&::#9C_8p59թ`81II鈛 BTrCLh RM9&o9> [3YRϹGT_6myCM::=:Moq9u: :}8~ :#9^@f79!09Q<:z:V: 渐ś9"9C089sn8i9G0Q:B:bn9 :9?9A::I|:: l:$ŗ9EjQ: G:q:̸8Ru,(Ea5G !7m9:81L8QT:@:97`8SB7C O7r۸6Bg99FM:9:t912]9 ䷁:|8͒9 í|(z$8?Q2nX 0Cɍ$99k:K2:i9Y9L9 :D:8~X879:YF9\8+}9k-8Tu%91:&;:L9ϐI+r9?U989I8'R%X"9959Q!PG9$ sMb.M8:ն::\4:ӝ9L8vaZ B>9 9%9!8$[9׊9mϹv |ϸ.ʷFe9[ӊ7(-x&9ڥ9L7cv"9==/8V#9839Ů7L"@|vƹuJ +n:_=9H9f:mg:A :up{ It9uQ8R97tR8 ٹԽiX|۹mg89Q*%: :<ոz)8g-xAg|.g8S8 }9݆}9\9/:X=:z:z~8yBn9/9ј9`:n| :WC*p cςʹ(o-9|LF z29kp:ЖO:_'::(Nh~'OaڹY딳9od :(:V:.x:0P:iZ:0:J9!]91F{͚9)9b8f9.9O9ۯ9:r9<%9S09&98Y{S{wa9y9Ҍ9E]f7i9a *9.j99D97/ZͧuB|*J}˹$7ĹN8.cูl V^9f9 29u'::v :BJ8:f9{C>?UM۹A-@l|nDž͹6ɹ< q'2HDBu6MB'8=9k8 1踏ԹM0[j8 9z*<98G9F9fC:z56nmڹ:'9K7Uk8rZ9bVA999s*:́g9&=Ծ8\':g:9z/G8XѸI @!7l9`auo׹A>ԸM94w* +:Z: :T17dn -ɹFr.x9Ͳ:9Ϗ9.J9Y`:ǖ:!9QAŽP?3`=Iߨ5878Ŗ9sn8ǹ'Թ489)9"ļLSp'9] 9fG9V64% 9q9@¶,^D_ṓչzf 淸8P9)9z\9&:^::F8x/:y99Ž~:+Y: Q:- : :aa:#":\9GF'I7R9}ø6e::vs:#vB:y):2:n:˂:m]|: RX:EC:R9: 9/v9:>9v?:Ń:iJ:9(:U:Gq99:'6?bUX-sT iă81޸D˹Wm7T)w8\Xﵺh%!ɨ{Aָ$h Qs97CsYB)z2Tyl-]-9J99Id9?-9'r:::W:A8Gj"^9I197=9}88&Rli9c;(:)B:}q9Z97hy`Ը$,#χH:S(9o1e e'rNxe)mk^kTDaʅNFeJ39W8,4S$B. qJ)\rm~9"{9ћ9k9:9\E83O4"Q46bx8/Ӹ}8_I:>f:d59L9fU9H8c9Fj:2:úR_9So:Ⱦt:/9" 9%τ9;99_8nٹX9$:~c829mq9=<9G9aӛ%0r9X¹@`W>NA "C8Ѣ3q-gETriB7+C ?(l`_/H@ Wv6| ]g|L9ҳ99@8x8ัfҹ ~~ ԹVݹ 8X9:L:0:=:`ա9l9 ŋ9yD?9r969`9xOyn\k9q:6uy:ά99b99;NQ929;9.9&`& 0J9Q:9U9/N&v|9\ sݸ2_yx, % K x 6:uw5_ݹ/C&:.8X9H8+:jL8ZMoJ?~CLm7-¹6l.N8?99^9w%xi\9о993983:N:k:oH:k9F69^92:g94 [|!78+ƹo3 󮋸H``T9V':2::.c9J|܅ud9f9J9@9 9L{D9>$9q6=9W39J9:>993 :(:: :n8Wh,8l9H>vuҸS(?1Pp)LԹg8~"*7URX簷Z@b Jf_P9,9X 9!+594twJԹHT]D9K:Y :j(9i8]v9 =9sp8ḴRk8I97 >:e::ofD9|cyp:r:B@:o1X9;md9 o5Pyi4֯ 8M[ķqI8\¹b n.jg9ã7f OT(9"9\3: :83D87nhWι44-=չ,NQrcrpG9A?L-'-ngcպ7* 9G7/ƸZ ˹eiXO oj0Ҫ]>}V9989S:ym:G&:Qh8]88Dq:A:b:3N:m:9@99ۉ8h!PdK]h=a PMͫ99f9g9".592o9r5H<4:_.:t187659ҟ)@9098̒[94C9zd]9 c98U+ޚ68YZ2?Ӛ VurعʷiDKE9o/>:ף{9өùaUŴ8a 9J)R ![$86DV8y899VE9C8΀9Ռ;:v:) :f9A/Թ`JTP9]_-:ɹ9ur:D9aw; 38y9?9V7l¹~dJ-vGֹeF9ĺ9V= 9"9:?_H:s:A9t=9bWS3n9 9#p99 (R9yf=2\!>޹oٹ$C͹.knۤ9A99n:-+:ńq9P@߹J FZ39`9.6񹂁ƹ !nu"ӹv%.9{9|9w\W:!D:9 G9 *9d+r1ù¸4 =nL999{99 .9D ::)99$]=-ع^f69A8_k'G)7Y*YJ|>ܚPN.չ9m9x9z2:\:9:)9NL:)9߫8!d9vr99SE :[8U?+o9} 9e8?9D:C9 9x (wF^ʹkD+;D9:b9ʹqV=Z>^Ґ˹ji3=_NG{}nո\x9\9f83ֵ8aQʌTZ9J:6"e:$:>8 8i8yHhx8C`-÷=93 B8عsq9C9uƸE7 h9l9r8Ů8:9<9EzֹpƟ,# 9؆8֪t%$hD!9wc9VR949vK9y9a}D5d29h8*998'ŸjX#9q9e9lE9'9|89͕z9bƶX9<8~USg둝<[8o8-=9H9 8L(889~%$;9 9w9 ܃9E 999;i\mZ^~׸Tˆ-% 8o :ޡB:<>:S :Ҕ :95r˸ U98$q Μ.9d$7|S9un8t7/avy08~7sk(@_/\'!% ]x}78s9A>9$69=8ɲ@8){82y\dŶ0U7uu+Ǹit9Y* W899g9$D9!3Qiɹ>D^E9鿡_~_pˆ||ު8Y9$:X:z6t:cI.: i9 S9z SMM^/=@Ea~p孹G ƹʹte"ҘqlùQ.![-`$P ƹewft5j9 :::98896/7K*o, bRָ.JClCxN8Q4c;CQ×gfi\ ޹QHNBPU8928\Wb$fw;88+D9c9 鸒94:Ie9kϹ 58"G8|9;9:X8*~<9&P9>7,NUPT9H9Dȵ9%9P8l:Į96KG^G$9"9/1!! mggU곹,7J9m>5999L9O97a#۹x愲x¹(I-෼Q9CK9uL)C\ Bi9OqU9cl9(999V9I:f: :Py8)9pr9,A!88w9+7#::99Q8M!8÷;f+ȶtP18P7%VO56 9ҡȷʹ8ݹ~4jָFvҹW4{jq1B%P膹L8i T㉹D8^5'%)C/C"F67K_C9~?9f9y9 9jB qи#X9U9\9ջ9-<: O::9 98xpZ789FT9ڝn8'U|0R]H&丧0P9: :R9Ç;ºM60z8H9\8^ ak~Z99T:䷔9R8]7y7Ƃ?99@ۖ8tR 40\u;d^>XKX۷[~8DW988`F909?PbF C:[8k-$GY9U79MX"9)iq*!R8H68'8RBؚ789m':}959v: b:::8::mt8@\ϹS2-.:J=EZ95;9)8+~йH=eg8U9h198Qc789 r9/ :9+4ζ8y9 9IEM8790:ܸW}޹֤;u8h999*9ۈ :m :9 c9I<8#Rwugvd8Mp9yÂ9\ :9:ʸRlűM^o¦983l::: #9d 8]7Xz(7畽6R"8=Z8ר29')9̾49ߙ9Pl99H9I8h_DpϹً u%^ʸL^+9jc9G[:b.9P988C,xxXGQ9\<8wEБ9i;:z9=T$8bAQ929(۹ x#Hܖi?8䓸*s9q9"5<_8{99v9b+80#N؆7T995n9·|)ktf=7&8.2p8c7-9r3:?9i74,Pp?579t9w9aw9:>9#P9j^#s99.9[>ซt並90 9eB8)%߁Mj$Ķ}4Iֿ 8{)9M:]ء9•ަay*=d跶T+9197ji5 $8xZ/U7F),;--U˹kgKH>RkXR9 -ѹfڷ%;t9g-959[y9Hz79Y9鰸\u˶!Be9 9':p:s99]x{P8_&9m<8떸49h8Xqַ46;9H9 9H}tCE99e9,N:::96 O@X8ɟ9e9tY9Um9S_9^,8l9@99V9 699ي:9_hr68RZ4-θqekN83~9M9w( :xR9n&if!!^8 8N7|28u*9W99Tn&7aJ7R߸ԗT"๹Ź:wH8Jg]aܹ6Yj8g l@ йJԶ培E#͘9 9&m{q'Tѷl8!v9,9Gr,98WL7209:69焹fzйF8i999Ѥs]Ơ;¹$z7h8e4ć8c+8`U-7*e98h9 ӹa+Ù)Ѹw6"Vݮᅹ'5d$lM ⹖#׹c#Vs FY&4øV߹,޸;9e9R9Q9V9-9@u9]ͷ}hV99d8=y7gܘ :B4|5|m@2eĸ&se9;9@9ə>и2L%Q% l 78+]b!+19 zIvs/9U9!C9[跞c809O_Il/i8Q^.*7~7724U9T9S;L.%!|M9[9D7k}g4kcj'C<֟)|#n0*`6|>9U8~7#|_9:(9sY9†8;9w92:ߦ9[YsDZݘ:999]09{߶9eA9(8x8ϚL7JzM<9/h7ߜk8,9OU9 8Eø8?8p=5s2k8P9,69P99c2 ::~ :Ի99ɺ9.*9 qKAع X\zu|299 !ĸQ8Hw621t'=( bi58׋96y9T8YUM-9Ӹk\VtN _M7 9 8z Y6 7e8Mrȟy&#\\ 8نs枸:.8 Is4;:99f8i\9а9i9=18h99^9?9;8RC8^T8_--&lVl;9r'9b9;Ѭ88wrdbVd%B߭Nn8U9\7ݸ5͡-M( 1H{]˸+=ۂw͹I!∹7^9^9Wf9A6ȀCJ;u8]9Wgzi8899FԻ99\998L8Hn59R+9<9 c94/:>:9t%99T49.b099Q9C:~9d8VѸ-Xq79o9|9d9KW9­M8ډ89sv9\8s55&z* ߹Nѹz08p8丿X8}98*68.6:]Ϲـ׹@Uf< 2Ĺa'8ԹxW|_C% (񸁧7Uiw僷atIּ8"I9Y8 IC8s8318 @8>mB98烹*ݡ}ef݃&49ƍ907Rg@Z8w-78e9197x68xR99bD9e876Y9U9Sv 8c$0zWoCZdt+)򸬂83L49TC|KB_)Ĺ/c378E`9VU6|7d(Ai J5Ը:b8:I9H'9Do8ƸJw>oS#ɚ`_9R99K9292׍8 08c8Q& 9No9-9o9?9nm9k޶b)P"3(uHjCG8v)9Q9z{9u9$8Um9:9 88`77iP8pBu8'|C 3>8!O9|8o8t9kj9 $8*R/VDFqƹxy'. !B#ǹUG18J8= .ظt÷퓷b*$'o9E9991d98Di9f99[T9Â99a9{9998Ȓ[g3VէH޵v ;}&ϸ7jO8#8/9*9<9)'88o9~949 09)}й6ڹH1`87P9p9;9 )9DH9}{9&f8ay99ha9k8n.8< 8Z8cH98@k8I988 -90B8{ɸ8;J9U(99R7Ҹ<03?˷%8nxukk,=@|8Y>#??2ĴPuùū)QW809:8 )LMʹϹ@ ,7Ͻ 8?o]ԥ7`368WG914/98dB7蹰S8zI9;8 'ॸۑ6tڶN@G8f9gȢ8OB<9G9J8&9b9fX9B99U9>9<9 6x8>+8197B88?82H yWxӸኹVmr.ꉸ<:x8pR8SG9.ʫ e=K8>8eg6G8L(8aX/~.iYN6=D80bg8\[9I 9Cxj9"9KH9Nc999s9:Z:@9:8'6 8)974tQ9<9a9A9D29 D<6?|+nryTل)1b L8,ظԴ*I 81P`9Hi98X 幨M⹧;m%vT8L928伵*v8<9v<8Lyv ιJ~ty9 9=89`Mז-)$7Oe8-K87 9?9m9D9*?7j2D%G כ#((XԹ*>ž9q9:8();s ʯ68;2`ylA'vҸò{rJùqh8 9I$"n8w8j·o88Go786n9y8=_3's9H9B*l99u969'19d)9p9ÔR98tS499Fx9j]8"999+95n8x87_*8QI9V9Gf94N9 998U鉸929_939P978jS8Ld9Qn98<9]9J998(h814V'89q99 9^y9m`9f8q8+99>9(Q9R9-9 M988j D 1OC&/52;+$ljY/|~njnsJ18f8o޸׭%'57e68 @&޹̹O`#9a199E99(9ʺ9s99ﱗ98;9W(9T+9:9L9N!|߱T{h 5m}[8/9(9G8<8]%9R/uoULnl^798Dbd9C98 z`¸%![{k;t)]9z8{4l}/Z%8nD8o5~77`8*9 _958x9;Yic{f8]99t9q]9Ze9k9Mk8?X2ͶNX:9_s(8#sG &9n9f2G72=ڸc289)f8O'379X39Ίc959:7(X88ѷ`@иoW5$QlsX打'Xk=8:J 95Z8!8Y988e9L%9J9ֳ9.ȍ9\9-8S948Z۔68T9V9<'8k\+PиZ99m:9,h9M8b]9~E9(O,9$8 75gDPI?'+`$/\7882^¤ͳJHOD8#߷9OCZP0$V76UJh99}99yU898aYPPe89h9n8k/89G7rz7G8-<9؁7n65E59r{91y9Q9|9E9S=2nI#z\Pœ=2?\5F99 9O9J= Jl_g03q2*n>r筸srҹkѹ7Clu%_6)*gT͸e78{j8(+<$h 8p775H&YvV 89)878Cz77uĸBTx|;Kٸb"iBY(J9Yg9tr9s6˸Q8hd9yvQ9I,8 <]_ !9?9_B4E'I8)Z@99w9:Z9 #qte'BA(θ42#o< C5ϊJ}Mgؠg8I9BA9B8&>8yE9S 8 7J8X^8k959&6Q1b7ג8t· fb5gsU&)߹ ͹7Ip :wf`|Gָ>{i˸ b+E1|XPۊ8p<7HJ= 8]i9|9K9@7Y)x/898;78nc.<8=8{[i7C8BF9I88P28؁8\7F* !Ce87Y9׻8dXr^'{}ܸڹ3a7 Bg그%q8~8>Lϸ(L`Ws1Z8Z:^8,`#9BΈ6b78b8vv7󬶺}ӅcjߢAP72(7ʸ^OմnC>4N#867˸)R͸Uw<ǸYx8J1c˸""4-з08 9 9Dh8¶8*@8718m5C޷ϯ8R98?=߸^fxZ›F=Gь5/HL MT?R9@{,Fvn7277Vw2oB8]818. 6Б78eh8+9u9}09P8 `وm8i8r]8, <8 987iGL808¥̷91ޔ\9}PN3h9nURQ9,yOSDE(8ć5񽒸lkFXuv7C8+͸5x6n+ U 2mHIM$J^_?lp8:; 919q(99K98h=d9}9ճD93H6bD-^θѷt|8'<9gO98A6npY'8Ƴ8݌8F2We$ 6RI5j((#x} iv!E/)_>ظ_8(9A9*39A9E8R8*f8_"<Bθ] - øa7 M9X98%088yG9r9N49ш 9.I8v8 V993e@9G89n9g9К9 9c9N8%8%8}8%7)<0.Yf u/77*9x)9O7qŸ~d!U/pҾo3-v {Ѽ5-k7%9 ;9a8o98*88ɽ8С7R8^6987#B8O88G%Lb8/?i989s9 ~9;9!7;X|8M8;8R9c%9rL9|:8yt8c7"9d9D9hf9dž:9v99т9pU9+?9$9w95)?9=9 9}9YL99d9Dy9Z.9$)8j8u_9AΌ9?7898.9Æ;9-#98l-Q8hUw LB_*@~8Ho7[778[7 ʴ H|))+b8Cf߸$6>e7v81=8 QҡfxP 478q59U9"9N9f9T-E9`D9la9n6[c"8R4唛7ɲ8Qc84EP |q8)L99Q99:I9^892s98\D6Ҕf;m4/666^/ոϫ7.O9{;9?M9-#9~;9>z%偹'[W!q7^8#78 bM9-T8S` ĸ%Ƹ6E7K77o9u99I98r8|N89A9E7ܗLRٸ,8F9]868u 9\9O9g&9]AC99Y:8Iiʷtи\+q6ܢO7Y8n_ ȸ4FP8 9nl8Ş77y8?"9 9L8"7Z gK"8P9P}9@9u9i 8~h8I~gekAfƾūݽ8X8bL99F9s9_!9A9c;Q985AҌ7=VP7Lj8_9XZ9_<98u8N8hD냷q-[77Ɗr2y7=8I{98tRxOи/S_:g]y_$ƃnT7 Tyz-%8DZ8 Fr9z948E~SM+6]X%9d9Ӄ9{a978p0]Ƹʴ7*AQWO8T(T9 98=8i8#7}7w8e87= #v$7X8&m􆸃!5qѸF>JۓZ։a\1f%^.Z\9{691ڊ9)9|2%b$=;+^xfH'xpR/ Ѹs0o79k99 9ɯ/9,~[ɸҠI>8;8Hn8ckpLp#C5'bz p೶:259a8g0ɸ ˇvЊ8/9K84Ts7_%]6,҃78T7` 7mηc  7u7Ε^8{f8xAn=yL6Nb[8,9]8B7]B-8@8%876÷:P89mo95d98l(8U78{8B8\8M8VE8`8o)gnei;z޸.C_8۸579S2̸qVT@`lkZW259Y@98-8yu7" Q`7WH8JŶ[ J7?<ѻ׸+gf& 9ΗT9ûU9R988ﵷO2Y8}h}9x 96c֨aLf8979<""9 9(_9w88O8+84_7XKy=qhFw[.88c/7sӷ.Ḯ gx`}7!YF-M-`="k28a?!$PrQ8e7DǸ鸿#ة縓}ڸTT#h78{_8dvӸNTKP8VE8lP8o.8{9/9џ8/߸Jѐ3@<8 9G%9@Y8H i=N882U8Z0a8c|9 9k$8#jrG8h9u=9X9B99C8$cROsѸ)e 9KsI9? 8 Q8܇08VI7K848\F8Hz7X;gBIhG>*4؂8>9)9>9ivK9^h9<9 8 S;ٸ%h]K8&9Kx8#X7¸:*g7u8u>m5j5cP36؇88Ml,9 9899;lA9_9,9U88H,5׸k!Ks88Ҵ8)27޸ 97 9>7:89pb8#,E۸7N|7y8g767 E7)8AO8F 8^8~9RL8ZH8ځ8n8888Q9#9-bS#M.E 踍k?l{ 8u6 0K `"YոȗTK=8Ju[8{8L!8ǁ7F8ȝ_99I 819. 9r88ϯ8{8Mn8d8|b иՅ{ 1 Y88\969^>8=Eɵv<83{| J8r8 $j77Dڍh]Z|h7r~ Ըd1xofpmA888O)q)7mT,/; oGQt8,Ϧ86q\nuͷ&ڷ8X8H5ת7z8'8-8YC7AV=(68c9Sy8@8k9eB9;9K9M8ˁ8%8cE8/f8 89hK9xF9ʙ8{ 8h8/9e8p99M 8Ea8ST8H8t8 8<7%8c9RnI9FW9U9"9z7?W7'o Ŕ4Nr78g88877 8^<9]&9;S8 ˍ̩O6Z7Gbɸf#fV ḯt;4-:;>|{).^۸D7(&tXG[8DC$798h蜷lK7O@8Rp8?r)8\!58 7Gv07 `'3f۸=#La+6X777 8{9ڂ?99I8X)gw&O=E"=ӸoU8ܮ81278]8739L 9 8!|87q*7C:7C77FR878I 8j8G8I`9}V98* (:Ÿ  /4> qt̸N Ʒvk\ +*rw7ޫ88.8Y88B7E/x떸ci;xɵ!P1h5G6޿kN8Y9PU9&9I836){}߸f88"7w9D;7@8b 818oٸjNľ?6j8r;{8մT`:cמXc[/Wd3z8ӊ8]8:q948螥I5 :8B:848i8ѱ7b 8r8y8A8c18"0o|䈸2'>6h=858؄ѷ݈ diߜ.wi͸h,7/8q췤? 2-=Z6 ։jX1SBAQS S(eX&n8#9f8)s9}x.8I8M7Ra-֝7] w\s7X7T(&&yշ7U8z7Ђ_89I8O6K['4,·K88f8ˋ9-9-87;ܷHM7r87R;Aa8(8g7 $i8/88&ޤ,D¸A ؓNʷ50\>&7h88˗8C=8D<.}8S8H88ë8w 40.},7Hz7fr_FSDt'7ܭ88B~8wH8 7Pg~#DcAܸ@,7V8 8sv8+H8a;8`%/8J$8^! %鸸O&ߴ$sL5U^΁7v|D/]Ii:=o\ְܸgA+7)8f 87޼4xD288 ᷵7~]88}7?k@P=6Tf8B9988>9!9u|8UY֓Y$D 7䷧Է.#c j7;7퍶Si9PU6\<**A ^1m& 88iJ7GXkWC8W!8H(QV$z @V} Ay8g88v$87882889?9:7ո4_E)7m(8+8mO8 90i9NB9i9z8Da'8 7p^6387V8"9888 h8ޝ9?#9oc8dJ8G8Qg8_7\~2θ{G^h-鱸=5E=6IEI { 97TĒ8_8,28ǟC8(#;+{@d|`p7839W!9w8jxp8f'8շHz~I8e8"8<8%d6MN*,"lxOc7h828lc8|5 6涸U#ƒ޷큊66c7"8w8ۍ8Sd8~k8o Ϸ/YȸZƓ I y uAUn[G݂>ϥƸ 8@ؒG*g_Ӫ0`Jf*P;8_S9.U9<8 7ӷQ7p/B8:4?>jf6]y88dX8t8w8K-9 @9Y98Y8<g`8z8l7 ͓ !r7Û8K"8"7a8K81q5x=s8h87Z߸ܦB9S])/I7|8{6,i6.uθbm)^1~NYm"8l88zq7c8=f9!,9H8v86k87tsA <5~P7(v*r7ĉ8Ē8\Ƣ817y8898v88;n877|7]'WU3lO:9/a9.//98 9$9@98\;8Ȕ7J88F88>ϕ8]YM8z8Y&u8XxQ6, 8R=7M+8k8̕6/!ѡɷ7Ƿ:u 6548շ8878}8B9/9+599C298#998(8W88-8Gez79g9#`!7ݷ5 Vx˘6%Ѵ8ӟ7^88'S88;Օ8}? :ljk798*s x89M8\t84Kq>P>O0y2sEK70O6ȕ{#8U8ɏ8z7޷>=7H7|YNCfѸᢶ 7> 9 i9܋9{9{%9+8[8h7椛ԸF']ID?7-`ӸڣӸcxO}cR"6XʸsZ7 W 196_s\7*8L948ٺ׮ 8F;Dhָ=ܸ*-}88q0 98H8$8#M9c8l%8j(6ًǸ6n8A98+`7=c89C9T878C88vN8W8&8{8)n7P" a7-89858 R8onJ7nWY|`Ok^ٸs˸,W<Ć3WI#a#JD:I@̌s88888}׷8>r89?8&U8P)W8n8L7 9"w8 8I8I8LʽPb|!or4WGG뫸YLmK]87c8_888ᝐ8?8|qNDpg^68uY7.^6#DV@̸c߸`丸3-kda "[&p־̠-7x 88^ <Lr7Ǘ8m&8t)s񠸫n6]7 7b7x8s87H8Z;9;<9`098G9Q9,R9t:98Zr8Z_7]!S74f8ʞ8>j8ȼ88`b8A~8Z88}v ']@po7b7U#8_.8$!,E67eb8qM7yɷM\ 7X'D]'dյ779݇89w9^888888]8 67-on7R88kc81j87Q7]8@88=(ѕS{Mt5 NaLZGr0-d͒|`gFp S Dvc" hช=sзE&[8$9P89\S'9-8Ҭ6V:ٴ©TSo6&7"7/8B889v9V]8WƖ777789%9ܠ8ׄ7"88EN8[7/28ô8#v8m 99?8o^븄]e5Z8 98/8ʂ8E<8'G8>a8$dA*ۂ77EVᲸB:8p8Ip8ԷIqMIɸ1t eur8v8'888ɝ8/68 tj{]7"g848@5R…~s'm+l65$8d8\9}vK9s9 7<6oaC+7D17gʷDU8i 8| Fȸ+*YgݸOSf:Ҹ̸oyB6&Y8A9nQ9#9 {888q888|.77&7 88P9l9Z88 68M7@6jNSu75>qʷW7dՄ8:8a8W8685둽8b"N!fY"iTkuʯVWd78D838[9kB$98e7$/t0Xo)lڣ 8kۚ8 8_88.g8˷LMFe}37T]Z80d¸۸H4Ӹk(4p78cԤ87Si鯸8鰷|J8 sm8L8ƾc8*8#Yf6T(u%$8awG 'H~*/h7"mAWx6Cַܾu%;zF27Q88 8N7JA2 7<88W7Q7V788 c8U}8dY8U&88J8ڶʑ7780*8k{88s9TE7K7Ɓ7Oӷ8֩v6&d 8-8 8ʀkڸ¸L8>Ӹi޸ظ(]y>ɸO,y5ѷ|Q&(jQĸɖظ*-¸xkY9*7l8$8׆8AE8x7хaUhȸ÷f14͏8%A9y9' 87771M88P8va8 M8d887 ,7~G8%8?87&* v]6ǞhJ޴*&Z8FʷB*4~727Tݢ8CO8gD$. 8q88K85W7:඀78x67 i-8ν8S8 38k6ׯK8s88մ8K80۷868N*7íw8rU8R7Fз椸61$0K Ǹø$#07^8 +8G6\TH{'bNZ˯%7 r468&8:7588Gl8,kkցNj_W1~F7|f\墷{7x8m8R ˡ6T8r87zIa]ݜ}g888k8\8h}n76/]868lq8648!56u748a6A6\7*.73ֶ[7p6h̸~i5Qڍ78Ԙ_8t-!ַM77g&87gvQ/$) ٷ666678Y8888=$8<08ތ8#8,l8!U8M7$ڤLj4J;R𷏐971l88"Ϗ:m} QIe kN28&8:9L8mR6ӷ@I嘳{c6~z7A8.8q5 6#6[t6qc!D;],Χ5qsʟL;Wo=m881H8o8´75r}W x+&(Ըic^zM2h5@cfY+ҵ "*7G8m-8G8t6fBl7y8S8k*8n-8*n88x.7Ӡ 77sPa%8!y8G68|7-6NϷ6ك7-7趈77hj8M8I$8˽%87717c7iUyӕRP2f_&XzJN4̞'ָrnp`۪(ɸ + T2H(Ӷ7V8Kp8#898z8h88=䐷-7a-8F8_88І58j88380=8.\,NW8_N67 c88E888||28h38(8D8O[Y8S_88{8v888gx88D8C8vz@EJ_HtǬdi*ٝg*5_7h8ݧ887JpIe_\47Dhm8a8Ӵ8{9"9B7988q88WG89{8V8k 7i>8T́8<8O8ؿ7>Bf.#Ƹ佸 Sņ$M5!H3ކʸfڸ͸s/,SγIvƸ6ƈ; ,g\ŸM5L-7+7 b6:~w,\O OǼⱶ,U TxѶ"67Ϸ>oiVX,©g7If98Y7t37B8v8}7: ·7#4WϷK¶U7( ϫ7ư8׼8w8lP&4e`$7M=8888Ȅ82}&588<68g8w8J18fB8`8 99h8铭8>8 G76[S6m%8 uǶnC"[ܰDz~`8C`#⧸qen}CSB8x8C888rs8Z88?7:!8+8\8Z 8QH7͙7Z_88I8:9)9̢8.6Ҥ/YV 7f"_c#ؾ4n5j㷶I䷤)677887/MC7/聶z7`7H7<7}TG^7h87* "Z׷c6훧Ѹ h~7V+8;e7bͶ7 68P81k8@K8_ 7RZյ,a cmוl~V)˷ȷЖL7^88,݂887ϮO8"8鈍8p[8+88@88v8v8"8ee7BW66슯7ɝF8]88K8s}8+87ӷ }ͳcT݁awfR&3=17D)87^R I6}76~Ʒ4ѷ66v8 8r87K+@@n>G~JW#T7 8&7EQ7!8%z8$8JR8R7e e(u˷c;7߹7 &7 N%7m.^37Lt8o8C7u7*08dy@8B7ZO>J)#Z788Hα7coW7?i6Ҩ 768Ҡ+x7%<7VV]ٷK4čU|G& 88058&>88U28H(!87C738y88谧8qK8!7i~8[8e8V8h>7~0 45IX7.8ћ7H-CӚ 7F`8 8ӷ4`$%>756ÊUgi%xַQX1?7d8G8>8"?`8qi8#\7h78R8{77n88xG:8X88p87*3=P8䱋8D8#|{A477[8SI8aש5W}78.t7b|1dQ,lO>~#$rµ^i6)*!fstԷF&5@)ʶT u5YG4ᤸ ӷ<6^1 {F)yC TҸKYP xe718=8Q"7\<7767 6vg#8}7Ϸ:8S8 P8$48:84j8@.7ZVZܸ˸xN p ,{y/noqb)y3`8}5<8727地'vaַI7 8M 7 )7&!7Χ77s7f7ɷ8]7636n*>m& 2&!4 r8E8,7e4ނc8M8C8 0#rNа_HU5rJ5'tGB5њeqc!}7(:7Ν6)( o.#Ro>~V.Y W6 f888V8i.8,6v32Y6r7JlZ8vYs8˅8v8ݬ878?L886%$X| 777ĸ 888$e8S876];̸ӸZKUX<ު?LٸQ Lz5_zP涙R77-6t6L$8r^Z8 ^7 DdA$&7uz8\8'#8(8 Z8IHnQ70/7<7\%8W8S@8ʣ7R)7jV 7WO4T5_jB ^vn<8 ,oԷIETFK75(8s84,F8O7:@B޷6#AOM'yoR7\W88(8 8PS88B88q%77:v8Z8Õ8垪8V8H8}72v6w!8[Æ8_L87˭77x@V7N"|C=87[8}888W8X7T{,绷fh!nXݮ2(7.86;817gn\?dqI>n7.V7e8L!y84!77C7Sf8*88ܒ7;7m78 7{ݷdƷ6!a881ȟ8g87mU7:7LO7E7N7Z!6XCYOeR[.5Y848E8q7E{]Vc_Է$U ކI Q3Jp66&BQI˷>J6nԉ}2\7M䆷5E@776 8=n8,c8.O8o870^v728}R78\{=/6]7 8{7lt7D,88s:8@Q8o 8970F7›7^W7zP7E7-*8UN7bMs^l77{7u$6^UA$ms777#8x8g88;88%7.1sƄ6z궍6YV:5 6x7yO888|I8@]8y8H6z5K6͹6&v7"8!(`818V8L77Q,8˚Y8 ~8X8}7(]PҸk uøܬ3B7M:7G+G_07H8U7vt,'M*Ul81E8 8X7]7886x2nͷ6`} 8h87hߚ7Ao7$,8G>88w797>>83CS8(8`b8687䱷TxZci}:᷺o5`8 8EJ 7Eɷ?zD늷tnë؋s7jQ;_ u$66 jp?q'2w/+rᔷa7;8Ե7hY ļ6?67c8k83748Ff !lg6 B7L7h8ڷf4*n )P 7m78 87@8l 81}88[:75N78&>S8r8Ƀ8$u8!8m7j*6t%r78 l74!:[ַB[ڷ)TM7O48@!877MQ76H7[<7P77ZKx0N^$7|8yF8bk 8l8)(7ۈz5LMgntƸ6ʸZา+LR4|yp6777jO7`7J777I6q-7R:7M#6VpyO e'?,7tb77ap7 lI&vAMB>56]6fZ7_7U[7O6J6 6ԭ6!T758:r8詁8886L!)$7$ڝ5`oR3A+"<y28`hx÷9Pq(©R(^ Sb~ 46ZӃm2#7H- ;Ux Y-fն߄bGß94޷TM(,N\7o_8u8? 28`7IZ66q7=\6OG7'8>-8l8" 88A+^8 898M8&@888v`8s[7y6{Fvܙ6r϶^c77-5A'7:T6%`pI)JXbVط0Ey;TCs"J*NT6@6#F67SM72_7\'ѭ65S7SH&L7 8M:885sr7F3Ox$;J,p)gRN"&+_6 %շqॶ##78Z47ޑ %Kń6B3Lu| %{XRt>y[5`:7p:7ra%lLkѩ78 7_AhUlXW(.@"5X=M1V7M{ 8F&7ֵ?׷ s({A5.?!уrl;,?eq4|7sX58~888OX8X68v[8 v8hKl8# 78T7E7(75.7st5ߢ> 7̶6MV7}n׷ūxxwy!iBl2P5嵵7nm8RГ8$؀8B8+8%;48=^8:S8-767L8D6[8Z b8Y83U+87n63 :m+YڷqH<=PW|1vjaj ]f8Yޢ/:Yn闸l+~,(`$=51~5֝ݶѷWl0CÄZfIm!Bl,&枰718,7+6޷؈zc눷E*j@7K t7苝8t88JH88j8g8}_777y7 9M7۠4Me/x,ǞﳨIFeoܷHUŏ7o&8(8"l7_/M*~7Dv7Z7:5wIbF۱ˁ27q'(߶7\!87'˔wZA)XehH6@(8a78Au7cwr6` 8f8XO87 4lz̷e6i7)3Me4L$5uϷ F6Z6AW70 8W7dݷK26 7YV6wqG_tʶ!7~y8,8Z8$828 8Ls7+ 67>77Ƿ򃸹Ԓ;r-8nG[%?]GC6xIo7w1878| 7/6r 3ڷa;he+I p޷9Ht C9 ӒT1D4^Y5G%(Ƕ2$7L/z7ѩ¶_G I0]SH@6"K׮6:j757R8 888v8mú7~c77fx8n/%88p7Mv7 8i k8HȊ8s8#Z8h8ؘ7o㪷BkǷ4577Ыm7ϣ8G8 818[7BC5Ns߷ٷI˷*f)G07ƷGE4=4$ºe>7g7 )7T8#8vs8K8rj87iW7E77J7M6* w8[ |,s7H7aJ6rzj:QI鑸춸 u6eYT8⇃88g8 8,8w8ESf8>e8 K8 8V6r׶-Vc֘6j77G;6߉egk!7sZuTi*Y!a2 W7=37Tz³8,ƺ0طI3e]wtҷ" ䷲SE~77M.O7,SXe4L77޻C,+E7Xm[f7F+D8Z 8KoB77I8c8'vn8KY8eu8P8G88 ?827EDf̶Vk";37CJ7FU7[O7N>"5SGp66O *l6757<7 7Q 8+N?8`Qq8i8ÿz84O8*C8R 8r6\ B6Q6Ċ,sf8yb8}W87seγ" 1J-vOj?~7']pK8u3k6Va778"8v87si77537 n~45$V7ظ 88Py7Y8~F98(8ǭ76v7 9O8M88(8g8g8"wA81 8r7V7x7$6:3 hO77"76R3 Zϵs5)#׫~ϬP1Kt4Z!f7ݪ7b7И6!; YDd5öt&37L7t^ķ÷·η9a V 2ZPK_N߷?<fAw&¶c6TALA䏵z=oT۶萢6"\7u7 AN8C8i7}&7S?5b787.8N',8 I8'?8 8ų7ۅ 8_yD8J8ui7W6U77Y76&87}">½ؤlWagZ`y6!6C$5C6W˻##LM WC 䦵5#[$Kp 6K57q%7)7`cFV܉Mf\ö7m78p<8sa7i3 =5~Y]6D7;s7#x>767607777, 7&r7c6yJ{.Dp "Mܛ5[`5 =+ַ߷Z+*5V7p8(8m7 {架n6+VK7f7T777/7`=7D7WA7w fvõ4TT7c7u7?6SQm ] %0NcTŷ^ķ -DHD>%83 8dX7 7Oz7D7W7V8j8b83ķ7`w6x5x7ǫi77,7(B7g7 76`)!'.(xIk蜶萷ŝ(W]SNN ~h*eK7k߷3յ8C7777mY65  ͝6D6,u$0Keh\5$L,Qzoζg6F$7WgԷ#$!mō}JI'𷟟Dc65%7i&767!65$t67%b7t|E¥Wޠ6g7#7{w7738xR88!76tI;TC]BMзBZ8 ϲoַ.-44st-77S8ψ7`65akOh]#/GJg1.޷$mP 1Od]@,9yZ-z˩7z88μ7Ɓ>BWB|77k͒7O6h@Α67l7 U7cQdQ}GC67:+7-+7 6ڵ6u7b|)c<7[7_L7 ˷TĹr63|82)8s 868f8[F8g7|Qn~gS  7o777|7m87gԶOִ6,7J5,5듷[~PW淎3;>'0$p歷qk+7u7 808qK847o7<~7h &a_+I72;8ٱ0877(7n777707# 7:!pg䊷 2·DF(7977Uu7 F7aQq]8L9]0_46Z7G654{6y6YY47,]7/7W7.s7#7 774hjp᥷[698.V88_78_?x8ѽ8%Er813876ﲷ{jENBhʶ0g788'870 7-Y@c5]_$s5N7bTU%JQ6F65p6 7X7t:ѷ෯[Q6v7fE87})_A~677A8+t8KA8K747;Q8B876727Ă76uu]3hV5o5p6BSG6Sz"M緂K%(q{8] Hc6n/7V9}77+6j7ad78!87!6g04ۡ56<2b77f7E77,6c36ر?6 hM;orH.A߶9.m5}N-g''Hz6,8757b7͊6BXI7G~ȑ>]`K/7Dp7}6o#607o770r"8Z]88KK8B8'8y 8377F8'768o$8kL7J78A7H7e7 E71[7F7Uc76S yZ78b7?7g7+\e7C76Rﴗ0=Ͷb։507c7~7DOz7y7n7O7љ7I75A9E1зǷc}ܫ7.8Pp8 i8-8f6S_E73=83&8F05pheC~(:-+ðFjsa9A6ؠr ˷"ŷi){:2 L]磢)&7R78[8T7727k 7?6 !6ݶM󶩳_ײ+uድ"f6{D6ҷ Ӓ>rkPѷDķw8l.t11㷃0 繕0*H77P72^–f ض1Ե5|ʹ"·T&777R!8ԯ 8r7& 7w7o77#88<7E&O5з8$e6H7f77^7~2!6&Iѵgr7J7_7h7p7?}3 ϡNxŷ5?3WGP617$k7ܲ708487|6Az()*.1߷C뷽ͷnL"=n3 !FE շكѷ᧷< 7a77/7e7͌77HE7=7*7֋z76y@5U/~)%9ⷥ$[zHuQf:4"YնhU6 &OR"h |je {ַeƷQ3x47Y724ZrԜP966|IL`r6·7 lk7^8(7Ȓk6-6j 7e7B87s59}<uTn7L78 V77kx808w7&ayMO;8717f7=Ւ77/èkD^kX6R7n 7Y7;(788N7GUw7C7 27ς6r/7078y$7T2L-_ҵ6׶b'B%77s7Zg1Y$C؁7O7h+7Ե66PC6W6c]7&7p7rs7kZ7066R-7t7ܭK Y)E0n\s趪R[Cf6X,m75R96&P]D%C-< E4ӶWgNOnvط׶E:ٷ*I"u筙KI6i66n0`7>7q35ӿ))Y5}m7QN7y:ڶշ$>ƶ;7P7O897z6ؾ7t774;6`57B47弻cWU]7` 8Dx7=Cd!Q7} 7778o88288 8$s8#887n777[7$5{&V`(j6E677`u7 E7777Wt8$8g8}47 7F@6T,ܔ6]K7675-7`D7?7B7j7KmKRiboͷz*P$g*uMF} P4˶/շ?Xb(/IeP$ȷn)" `)hNh <49 )񷳉gaԶ|U7^J7/6l1M6v.7U7?O5Aڬ5uf7?80G8)8I7N47x7X7:77:7!4x N=B6u 8)xж>6c6;/$Xj<>8 bVX}67088t81ʡ7q7|97*78 8#77 7%7Z7 ؊5սb6+BR(mP/T+?QҠF)#=ܞB7)~+跕z5#1走6.7372z66 757S7+j7W6Foc0ȷFHpDO缷G0T#oZAOL.4=67B7+7W$7i7A7 6i7J76D oķEu5Yaq?~65/1h?GfO6+;D7׈6qO>6I7!77[7ߒ6 6mx7-7mDJ7aO7ĵ77m77i757nJ7&J6 6j6g<޺3ސy| @sN6S7V%7P7,76e6w5J5mu6jv7ui77x7f[7]ZJ767%8E.87p6(77e7xy7. 7 +8e/87n87n5M 6"5)Ȋe@~5Y^*7Z7!7<6붇Ł|GEP5 |_6 |7@77y76*6O6$6Z5@)3 77k7)5)۶rM)gX5r&\ŝ6Jʔ7t7C7|_]76;866)j6r䴉vQ50k /5n 7q6}H qd6Q7>7-7#27G;6f)h\ʴHʶʶ86\ 7 ;7b$6&L9Ƒ)!^ Lcg50C`gtX_=*顶67-7H6$6 P7k\6ɾ'dNt ~KWӶlqC1cmѡ777V7!O7nE7%k7.7s6R6[yfSJ4775O7Ի3gBl+|86=l|6h77CZ7k7 6]7m78t<8ܮ7 7XJ6F 727u7; 8P808y58 7{h7KP8&7݃6gcVruk5*@6@7O6&ַǬ6d 7S6I7CVД/쟋4:6o5LӶW"7r877Ԗ7' o7,x7k7pR7yh ?!8@ͷn⇷d7aU8&88:7ܑ7_v7l}eo?ƫ4嵬676%7" k6<Ձy{6EU6imk+ȷTˉ=+#B+T67"y7`717 b7<7ї7F77R77՞{76}7f{6Fɶ7+B1sӁ EL`e7 G*8:F8c` 8u76u^Rշ⺷&I԰6/j7}/6Ե|WW5̒6[7 27uI7tm˴DzA˷oOƷ58_ v67]7V07~췉E #_g6"5{6 37677W*6Զmͷ.4V7̡"6#(7V7Z$776g}Fr"΂7n67}7aHv7Aѥ7Q77707w7e7477~6525<;7h7sv52c]1t tе.ɝ}ܶ.5775sYxvAŷu߶< M -Ƿ keMrwЪǵ6Q,·v]Y6A[7y7S7u797Kn7W7h6:%÷ (~ݧʷA_?%o7|n~76PvQR?FRWM+GHFwY$ζ5H6(70767M77ߒ7ܬ6sLJA6(7V#7Zp7SX­aܽXit-Ȩ/+0ߴ^5Gȕ \GM'T92.T)>.55P6η86Ǧ7-7635`+776d6ѣ<3%"GC߶Z| \C!a`džȟhcpgMյ~rn50R.77-6_¾7*7.7w%7ݱ6_|[fq N *AKd! SLF?66#ݶ/468h7 Dt7akM7J78{'8w%84 8dH8\8CD8I8$Z&8b87*7 7W8 8 8477;77/;;u))F@ԶOQ5X6J7Rt66P66 %+*~ X*.E;AY7=aa^OBgϿ/nJ c67A?7V[7L877f7܂7`73"27W7<ݍ7U767777vI77:7447_6x6>7>27 Y`7l7TL76/Z66Mz2 䍵-l3M -7A#$䉶6գ<7p6krU˶6.`6K6V7<-7Ƭ69BK϶B&(JTZW䱷-l5cj6 s% \KoqNZ l)ɐ.H'5<ؖ5o 6 7g`7C7<7Cb77ص~Զf+Ķcᓴh7/7 J7 @N7/DY7 w7777F 7"R7B6e5O5Ӷĉn@yv1a2536S7h7a7Q6dV66677h 7H65ko;S56 6P^9sKꣶ J6(737Ӱ7)<77k47^7f7A/6LlEMO%77FQ77,t7t 7t;7_77o7j7T8z7$7r#$75޴6}7W7?655C5~e58^6{6659%J?pmf* Tܽ}FZP57f}7R~s7GG7+77:7t7u%7Z78?7Tҗ7=78/8m8M477~6\cEnL3D6( 7I 74q64864=_౷[ףI6ӵP{6ZI7LU77c7}X+7G5I_kK ݹַ,ͷqG~2"H#-!)^#ݶdR2EĦ񴷈۷D,Է/6a 赖_fJI3O52C7R7=/7ԛ6кW777d79 r'M%778E7z7`7s78'848ߤ7D7k`797{7877l7ɶ7 77,,q7r'F_6L6N9RE{lr7BϷ"~ H.>&ՐnewD )U [UHL'q8G67}7˷7W97( 7970%7p䳴{\Z+Jd%y!򈵗6poԶF60}6EeU/,P4^Rf6 6us@7|7Ae7,A4777dA7 7&&6R6b5! x67dD77t7{˵&]fǷu 4ܷo67H.6?-VųUY1&4Wu6~mz4_6a7򵳌h0BL669¶f?S`V|C3K.6"6P6Kp6qZN[¶ٶhyoζ7[5_6{e7,_76~p2N L-۷/qշQբ'b"8-)rhֶU;5F66666:6ZR6z5,6s5dʶxF\6ǝ67ݮ7776 ݚ6v.7 E7DŽ7Cμ6 t6G6y6E5&RηڷWYշUҷ޿mXŵx#x 3Ҕp1# ֬Jշ?t7tvkS"6u776:d66ggiȶo2F$67ť8x777hH6UM7ޫ"76AI6t6;7xW7T6/wUkҝ2(c5+D5/=;ŶGC^ڳ~x6615 ?6m-7'&75>6`36qP7͔7J7 77_77op7T07k6+6b6Q6bJ"-t F÷|T7e~h_|l;ŷA_v?ܪ6w7O6!5rg6 7^;7a73O7_76,56p66n5p4;~0"S!6,6nA-6`ULB\UIuw ?bN퀶2–Ҷ#HVg{`9&!23>7B7+g7=7H7W}776%6+ 676`K7&z7r.7n=4X?d6=*6u7}77/\7d77A7 <7a7C7"i73Ƙ7f7h7h7n 7I6Vd6RԵ@77q7n76_77E:&-E2!-zh[4$)G) 0ַIy) ꄶ6.e7S7v7P}77!I7a%77`5.g\uصFOd\5|6= 7F776 7F'7*65(T䵖6w'66jauHm'6q7t6Ya6}69IM7Q7DL7)f 7N6:6?7]0777q716Iᵃv.67>7 7\6)J6U:4667 b6y16rɶ}=\C61x7u47.G77N!7iA7fp6;q9hE4uq WB6vH7 77K7sb7TL7#hn&}BݲV k5$ R⟴sX6f7^7!5(=`& !Dg3;d}Kt@ LkZTo˵Oyec5X^ö6 V>66KCLx ^ؙw%Ch8ٶ>e߇5gN6fa66I]4:r&#bZ/nG]sY]NJ6mj7v7MF7 66*\?̶M`XM6B7\?772B7d7M7-76M7@6q6m7=&78q.7]7q7#7CM6=Ao LJ;Ҷ1𢶖_6KD77~7r7!4&#S#ۦ3+j,*XK {µv4<6-iKLmUYE%* c7$\7d76072}@6&۠k%# 5 = >R+{7*7,707c#76s.77fþ7M77"V76vT6~j61565F/524%5Zb6f.6)^6$6Ŀ 6 2Z"*.:4%5Z5Va.6O֑66|6CN5XK=D@7)PE%>aY SY%4k@+[%K;/ѵüJ_R>>e:6-7^b7(76(K5.ChA>I w G{6⛲666"6s6K65/737:P=7N7{M7))5*Ҷu'p5"1:vrF6+6.7D7^n7)c7ԙ7%L^Kgʨö L: `~Xl5VI7㫑7.j.7I+FҶԶ w"l 06B7#7)7=ϡ7#7)O6&'@ȵF56Q6Nge5Ч6āC737%J6pU55|5e5K{?K67557ڶQx1~F-k"!hpݶrɶ1E5?@tR^BJ& j\6Z6m(5&IŪi 6R6K6!6;6a<`6P(7^x7?;7LO6#6Xe7w7)r7 7SH5:}_i @Vo<㴩6e66CD[ۀG[n0/վ4-66>%656$7=7Fj7w77UCM76-5\gtŵZڶGNi`嶠Y5Ud5su!=pe :۶&-M?4< #ր`1867V7eqp7n6I/[?QS7t7p7KW7, 7I!36wcjR5}Q$$DͶD3ʶ`&00)F6[ 7Y^7ov6V{;엶OCTdX/4SKֵ;p6O656n7< 7bl7{7ԇ6D>)6SrUW->9YKq_ C {pb[5--I W@&U7!7+o7Z7 76$p9noh쐷-r ԭ6%57d5Clڇ𭷶uo&\6 7-7:76:Ƶjo󶪜e/&n׶O(l7FdݍeD!66765˙Ѷtf ̷з=nŶ*(5B5\ 6ŧ6L7{u77wI5dJB58RTEd$YCa+4Nt6626LH!d @7Ϸ \Ѧ67d7p67}\7>7`7=7k7x?76a6`E6Р:`JF$.C {d5Z6.66}6r6D6|6;6 7D7Ӧ7717Ճ6V4p4w6#7,I 7]v6X ~+~(ϐ`2FĠ_yJ5Ƿ+Z74=X5Xc6i6 B<4:6U@6`6o7c7Z7K7bɈ7 c7 7[J ?755PuԴH26.77\6NĶNʶ )hFɤ<ٰq4S66ƹ7776D669!7`!7-7#U7f?6 7 7-6px6@]׶U&\لq|Z6`77|7O47297,W7^77q B5=뇶] (%6 6E-6x=hxDGUq]y_G ,η7 xr;1sU1۶JGӶ'BR?O5N0!켶5u605U5/3,ɖP8}r"Na{6R67Aq7G7E77Z7Y7Ť78;7?7r667(:p7ɑ7T.7Q67ā6߯"7 SA7d977:6`68 *Km~ԶF94sPsIu$ |67'.7]`6Ve?ly{;[꺷U4 ޫB9m8öZ{;{T 83J @"ꊶP16x)6b 777 73 6MƱ6066O6 6>45$d.TԵµ >>#TO9Fy0sɶ!ᴶkn5A"n&EЀ̶٧4t686Wʤ6C5==566q.6(6j6Ú7C6 6&9趘".<϶jܡ4#4M6&6266866$q5?5͡6f5j &#xǶ;5o |6*7i7-716?dazHeDB״;յ6y6zV#7)77;6>o666y6M\65&665$5&+456)5B7a[7r47Rʎ6n^42*ɶtE: Ro+_&Rg5Ѵ962A 6,w6xT5酢h"'2t8x06^96[H67#6^5W_ j5s6V6=5!aNਵ*6y6855Y&66&66Z`6955I5Vi6'7'7lC71S7rQ7d157>727bO7,x7G6756JQp !E 5u 7ֈ(7+7'7 ?7~6l6-5ꭓ6g64N5ضHq:66Fд;Ŷ E$b^uH߶26757)7~6abPXjRChZT5%4d{ 2!͐ Ef8x&Նeg_\U|6Tʶ\uo!< [uI1 J Dժva6Z7n6e(ζ&HV2XQnaG1gR7_6D6 7J7ˮc7C6EXކ!2@ߵ36Y6r6e66ݰ7eG7'76%5'6/6&%T6{06'66+!E> ĵb/!yNOy5#u6Z6ر6Iq.WZ3緦S+۷=+\n鶉pµS56ʵ6b׼6-6r6 M66<祵W Z">;6877C7B:A7*^7l7O?76Q㚵Zٶ'OA=V*>E6p7X]Cf xw&*Wu6{W57RT77qKV6Ll:S%'s綐㽶5R66C7E7H97@7z6}6N5ϫLNqIb)(2X2ٶx* &Ii0Nx9>\$9.Gl?`[b 6Ѷw=Ķ4ٶ8!u4XRԶ]&O͐~5b66336bǥ6F6r 67_72v707wSE6T6絁ui5n_%[(6v6~5u}ܶBܶf.*]o'5#϶у7ۃՓu!/+#?T_ U7W#:*]HLVѶ/< r eE=8pT66a6[65,666G6sE6 Q4606+ 7 67I&,7707#7#7:+7CQA7Q79.76TQ65ozNT ֶD[\5؃6sR5]J7P6MkW6#F3&+3CF:e\~Nҫඦ5h6mL76󶍳N!qC|z 4|ڶ=tTDHM'5ja66CX6Ϗ6:67L]7L6p>Hpt5Ƹ[5I4k6U7Xj7sc784D7_'7 77:7=787`=6ۍ65]Si̙5r6Nky/1 oCzQ%*JSlȵi5\6S6< 68Ѧf}5ґ!5~6v 6pYg(t*y r۶}R]5L65Eb5d6oGZ6nk6M5wf a5J#7X7@7]8 7]7h737u<7P7 X7P:7؅7u66"{o6@6=k4-6v6y6 6b(7f7\7$7 6z5~K3DL6.6tP5C{6Dg5O6@50[4*5lgʵ{A$bҶIԠ︶zc\6{]7|^7 765zo6І0 $rpp`#& XvqL5qg6Gβ6!|7/7%76Eܵ#Ķ-A|FS(h.olڦó7(56m#727O6f[*ʶ&X6ĩ566cc6 $6eɭ68'7ZO7?/76D%59 }z6O7)776266$7G2K7R,7g׎6=S4xw/]NJ \Wڟ $666t66]4%wnLz/,ۗV>a8ϧDKද -z+7(5666e6'T4es{ݐa6eUr4=66i}BSԖW鳷áJfY׶Ta Vrն.l 6@j6Z/ P*[))tTl6T7UF7Ӄ97,6666A5[XAo/cAF@x0;Ƕ=`866]6g46Ӳ.N5S4ȕ2b!wKIc[#v/6'6 +6͝49^^I6^66_5SR5Ke5 IC55 6T6K6]6,6rE7 ^77%Յ7<77e6b3y 3)J5Vӄ|<V_lu2HUV;Cw 5(׶ƶu0RV4kP667777n7(7rV777K}o727?6o[6 oPrx¶;;mUg06s6Z6{[6Ս65A4%r|㶑kf*(iFA wI5H5(/CcYno%綁 ;I|C`EмlfɌ\*왷94+I\Ϡd኷G1޶utm׶^a-.mw<`\C5.(6Ɏ96mn66(I7}y7PF7?e737i87>I{7-7\7}N76F66K7GJ7V!7-~7".74=727JM7[d7t|7D7|~7Y7,.7$7= 77666YH6&=6y-6մ5P{$@Apd3)g˶u85Kb3A{WE;Ѡ}Epޗ*)X)515];bwT666<6066ͤ6V5V4% 5.T5mjx)67-.P7oP7`]7hUc7BM7%7J#65 2Qfgn@Z2;u6O 7!7 7W7-r7%l6lڶt_Zt45Ujt)l T|gH 0oTV '0 ;66 VL6u6w6656t66ew6TlPϵ9:+5%o5Dp66}6՛ 7,7 e+7S^7777E7]6N!6aM56,Q6l6V 6GfN[q![d35ʑ56Ҷ6UŠ6P52g5D6<6'A7z6.6\wwa[@cӵ4f5(5zQM>Ŵ{q567%6%.6&o?~zV6w66p6Ք77چ6hK6 o6UV6 ӜRyk\66?G6R6+66r5`zhTƶ (2ض]B5bȶ¤32RN>M9/+#Dvg5q6w6 6,5HCi̵G4Sj5qUiBߵnhx,׵ 4 5x5nL6Hv5+Kݶ?3=锶n˄a66c5CBEՓ샶뵔@kԶ,ʶ$!׶ &^ݳ7 6d66YT6C,͵bF觶⍶F[JFb6h5 C6ذ6W6 6ߧ5s *̠]+,жK6$񀵑 bdxA>qV!E`^ش+i6#06Fw6kZ669o6'7iO7l7:~a7C{I7/7U7,6@l6BH5uR3:b" o2һy6ڔ 7bD7!K7Y*7\7 "7)!7s@7$s6Ȃv5C6.7337b&7a?6Ku6 a5f`2u],.b5U`6N>6R)5_y389庒5>[5<6+36@f6U6(K%7O7c7&47*6/J4ȵ{bԕU9ʕRj5Nc5-蜄ހ2ٵj 7G?ʶwⶁT\W5笪6P6]G\6Q6ט647n`a7%p7'+C76I6qG?3>&M<YIb>)6ɿ67)>7!,7J6%5(Ѩ6j]`ʶ\䩶ݿT͈66=e7N' 766 6E/FK1coXd5҈6"6@؏6;G8Na{F~<6,D7և7Ŕ7Ms7U#]737746iDk6n6D6"l6Nϗ53,$666=6b6p07 7/ղ6D5s f5o526)6k66ܺ662666H6¡5\_)5A667|6o:6Ȍ\7:ȶD O4I6`66m5 ڪ@lkȶUT4']55}vs5uF6C_656cT"]*6B67V7n%7U;7(6ߙ65616=6?7G7+6-~6PH6abp;?g(ض˶z׹n޶$SypXǴp gZ4 <#Yxtr:ʷm϶ސ[:5`6{,6+51Gv56N6@s5*Q75q6z%&y4t-B66eE6p5o5Hѵ;`ZX*εQ<+5%6U6@2667776a6 6˸6bF6C5ؔG6N.66=Q66U rW֥\q61z6u5Jɶeo3,pi䶚w{qd3S{6Uў6.W655PPJ׵ %,ç|t]M _[6-q6[17?7S7K6}66c6 b6^6e{6x58kg ;DA*'ӟM'|v<K5@66T6`(5"M`B@ƶX-+ MZ5+6&7<7{I7xN77H7}7n66q 6I-ť85667-!7;6\466$6ig6m$6 >66.7D7G/7b86h6t6F-C6JF5Qtд%3ߵnKWA&f$IؒV5 (696"SᢶŶ2zԚ4L5öEFT~o?4`ֶ.UTNRG,woᶥӶLնx[xTߴ04A3[H]n"ƬS-Nќ6\7B7,716~$6&qO&5]15~5 5>@6r6V6"59dk*¶sf;YfV( f7?YW3WU<:"gܐ=˵5L<5'i45196 O<6R16c677 666pd66U6i6͓6vD6K@'ȶB˝#5ݫ6R5A5z5<5h5㤛5ZT6e6^6C6(86|p5ZE5ly>Ϲ[ε45'6Y5+8L`7lcURI~B@BzZd,tb4*6c6 x2Nةd V1. ɶǎfGtu-hDngV&r'6*kO6h6[66n5 6G6553+ԶUg6J5r6d6,6 ~6*&D66"_<72wU7/7Va6'661v6M97T+7;"7V 736ҫ6Q606"6$Ky6"5P?PXζXϵ G0SJ7PzA3Eq=s ZjQӟG[Q,鲵MA60f6R 7 Y6[6E65NS1I)3^0ɵ+([ĵz5T`C6#5`H4F5fEkdu6z6Y7:%7, 7B6Ұ6@*67q7J6 66f7(7!7ar63N5/4T4m515 (j׵5U6Yf6b6|6 6f6R5ص(+nm5ד5<@4δFĵµ0pӵaV;u 5 6s 6943/4$55<w9H`6N>6@6 D694]#g xf J/5Ii65T555:t5ѡXߴ^g4aFϵ9Ae3-)36ˤ6F6t(777y%7E6b6 25u3GQM 5/66 7676]86ȔV5Oܵ3Ხ2p;86H6l646=65 5?rw6|6DK6!6665<%O_mD5?655k 5&6m6d65,42Nu $<:24+96Y6h6 6F6 7Z6n6yc65~Ӷd_+73&6L˄666,87na7 Z7-7/7f76_66옛6u{65d55K|6bA6UJ7x"7S:7P?7 &7=797@=74776,5O$8OI0ڐT 4gG6[6666c6D5&ҵaO :*I055v$5m+?TPr~+OzޥHZB4QD[Ӷ[dXc f4db6˛6ZN6o/6Ce5z|5Ӌ5i53CkWЄ#^sCBAZ6V'6n5a55|5x16Cz#>ѵ"4ڼ"6Zb686-6&g6)>p5V>"ߵڦgmN5XT6 6b5D;5kC5H6-6휃6 m5c5ٱ}5]6d66i636:654. nصa;RTx'B} c /?c5p4 &P2)ʂGUDxi)*籶 $5]/g6.W6ݓ6H6ЛG66k5NL6Hj6U6k6 ?6R 7k 7x6_U66П6eG6-5s6I6L5덅4Ȼ@06}i6~6561i6e666,56@X>ڶ^b8ĵɵ&Z~Uضɶa|{W>x*17R䵩4Y|5"$Ub6H6iE6J>6~6y8V658=&OJX66n6jM6Cw6'R6b6}6e6?e6 6<5U4%03 6Mt66՝N6$6i53>!St)ܵJ<ܵ Z.^s5I5شZ 9p5>6YT6+!r6NF6ZL5X"b1=ôr5`86p/6>x5i13G%5y5H5׵1qI\)\6Rm666AE 7 7 776*7k%77T*7Q7~j7W]7ԃ77H76-5q㳭ݬA6%_6ʠ6ϔ66s6kd6Ks60;64-N.(olufp_4]{5O55@6-6'6n 665=6*61P ɑ^;(6z6Ĥ6oX6R6U68<6lX6qz66ۄ635JԶ_623N6}j66:6N5$4Xdp5v45x5a5 V5956\4眰8%!{kw/Mds4 6%6546W5'6d6ER7\D7=63_6*5k͵O5w95S6626 66…66M7*76O6 ׌66o7 7 A6]6K 654|45d-4oX G4d|\666'?D6i5I5?ow_戵N鵾2XԵl[G!{n5n/f̵0ܵ{oŵ#;6%c6{6 )6-!5)55n-6m6O6`6~6x6a61 656R6`6"6$6666aC6`66ӌ6Y6e5۵"I2E2)x:6M6F66Taq,ߜ5m16A@f65(sIG* ؇3n# mֶ^ ݶmGﰶ( #YO55z,m[ob5-b6ݯ66P6.́6^36/6I6N6l"c66{7fG7E776Wۏ6)5Ũ0Ĝq+6"o6>6) 65p05,355t5j5#6H*x6265+654{4Xm5y55 6$O6@t6F6,7R777b6Hh6h5>4Gc\gbqdEx95ѫ-GtF5 U55[1UG|A)a?Ѷ_ȶ_#S5kS5ҷ5,)67ڊ6}6ON6ڽ&6Kށ&Sk˴F414,U oE&ﶝxI4$ƻ54qrt>$-#(3 c$5q#6>6?6yN6R6q<6}V62+66^66@6n(6uw66666*z6Ī76[[6Z6 T6`6V65vY'9<5?4Tҳ\l56^M6;65@L ow_Z,J5c03^~r/o$o`AFl㼗 -AJ"4dd6v66ξL6!!6^5>Z,Jɮ5O4be-Bc5I?6kט59ZE?):#^zd繶xնjVY4i%AG~Ӷh׶BR 6~855oQ{N#&{h@{ }^t| H1@j43õ}Uȵė565a544,5)[E6Cd6Z S6ߎ%65n6zUR6㘀6i6U<62O6C8C5b;JM])lu5ܶ62B6e67~ޑ>?R@`3ۀ59e5`q5_)45K66Fo5\5 45辴D*Ο9m׶@qLULZ֨y.o%`ڲ̸նsZ XL0([ 8|5C66}`6TK6''|N~Dȵ 5?565:-i13 !w(4~EeiR?nbLz,lqĵ^ 6}66ȕy6K+6X6,6!.6s61z5ʮ#⣴5@C6 b7b8.7=C7657P(7%777=t7o6Q6Z 6y5Pi541qe/9*^3^t]jg[ʶ-[ݜu;\b QOݴ<95;6s"66_C6U5}3ֳ 6nI6 6Z-z5zU5֔55 6I6 6}W6 5V"gy4a5*a66 54NCP?*(5G5"Y41ehu 5Qp6O66u6c5sIR5#6sR656" 66S6.67HWB)uq< TͰ΄͈ƣ"%ǶI/j޶϶ԶB߶%Ҷ$"0U95Y6tZ6q6I0G6 65c0fi㔵ѵpqA4t5("6 6 +6kQ6* 6+66rD6f5D4I5`6l6 %6A666d6!ٔ6D&u6*6I6636U6l6獝66P؊66m@5BJ 5 /U鉶y a416<6bc5?8mOʶ۶&ƶ-@0m`KZhM};9^ u=ci˗島Ϧj4~d55{"Ƕuc a^H@*wd!4E1kܵh9DuEƘt P NAD&4GNG :4GF Zz,3ً4eh5T:6~//6.m6 D6a 6ݓ,5 ( T5>]6}Am63 265384E?5En6j6tV@6F5>35D8666˄#6T5m<4SGѵhf6Y6R#6554ȵAPǡg]畘&Zk48la ]UgﶍӼ#] d5f65.)f~X9 \е& 468(6-"5%2߱ba]|0*Դ7S1c'C5\6Q66h6/`6VJ6[SேQ@uBfWҶ_˶T烶NgzL4<6GGަ1'D#:@ ve Ŷ⾶5b]w4V6$655v5\n5ȵDn᯶Ӷa9mݶCZۆ? 15N56cW6M66SX6|15v ɵj=On莶n|x a36>&96[6|O5_:586Ђ6K6,5|h3ݗS^Q5 5Y5q5d4 3gƴGe5k5{6R5 5[Հ!|d55Y4KµfdM4Uɛ5g'WOQr*@sYi̵N; #a37Ex >NV'2 3P56D55c;~5|1r4PA$5.5?45/5R5;^5T̥bH˶5ڃ4\4« ._}uA+} v0εyUȵ3J526FR6l5pܿTTԩXhöDUwgTt|B(5\~6146q6(3D6JY5GRUQtkY[!556H6} 66xy6648n D$6T~5t634y5̵Z-pMǴQdr񶋴޶ꤶE-X0tѴfؙ(x 07HnXBG:Ł#4Iř5x6956釵p1ReUƵJLRhV掠嵓G뇶Ҷ}Ͷ* v6~66~6676^sG6 (`Oc8;0>ּLͥ#/!Y1ɋo a Q3Kuzմ? 55^a5! ǚZW4u4"5 5A3x4^4ƞ5D4t4&L5ʲ5MU 5f1M55/m 5x4[5y 6i0#6e06J%6-6$5-QCXHU505ځ5&5B`5}?5D۳1%r341325V":Q-ʵ:8L߉>õbHh46gv51T5Yz~eiNq5k66{6Xk5N7Adӵ Rڵ>4u=5:hJ} OXs'u*j4MbdG܎JsAn3(.5_76 ^6Pa6>a686H695g556U6zs6m M6Bb6j|66p{6ܨ6*6VgX0;Ev(jJ5*6Cf6H 6G.5255W(6ղ&667W5Oju}%}E.4n5s@6 p66:6\6E6<68G6޴6I5]J:ں 5v5!f5wМJ`.ݲC\R]_5f5~5j.5F4Œֵb7"B&459555bp5 A6d6G6}g6gw6L6$6Ǖ66%6F66 r6&6AOH669x6>v6WƲ6Ջ6T6ē5 5Z555k4ƣ L$Ƶgs3p %R @EE)05-6F6;T6>q656K}66*N6|5&/5uP۴35sԃ5e4\uŴxD5i606΃6ў5|4t53Fд*=4l5T6P6}6z6!6h^6I66L6B'6465E6^666%4ĵ15*P66K&66TcZ6*69)66I6?65KW):=JWj' 3oT:~c4~Z5'536n 6 95517J⼵S 3P'zo>66_6xQ6~6655 $5]5`Et=YfebKb4DV42본TdJӚA5j664e6 4PⒶ4v d25\M557O85F'5? 66ȱ5}5nΑ54+5z 5.S555{e636OR}6(6?5h5D' : #J A4´ƴDCfn4524^+񵊸\t0e!uP[ڵCB<X4?{X5I@%5D3*}ջ1PE]:܂?5Ŷ.ѶDuZ rݜNꖶ̶I p 뙶ɼ]( X,pCҴ;66|65)ʴ#um*F[E]4c"qĹ1!uR-V+ĵ&M*LU ;8z}U\ Qҵjʔs24|" T2f*hT׏H4H+6L f6^66?4>54n<1:UVȵu b^I240558q(ٹZVzfmH[d:炶 e1)RYl\$zȶ)ɶټPnI1@ Z80W_25_%'6^16T5aQ3[^2s55<5d56Q`6 Q6)~6p6/6ć5|@2W+w"$GR^ڑM5[6"6Б66F868656J6 166"6Ӷ5{55Hޤ GCص_~,5e3WCfqS$ 45j5,$5\D5W7⥶Ӿ՚5W5bû55֫6쬘5+J@FKwH A[=Ú|:д+ԢA"5:506.6R^,6!63R6<55h655"\5{Z53E4|? Lӵ=ZS3dŵΙGv{|2 .6޴5G6<6[66Z5?P575고hG-qk5_5$R5Y5Pу54 }*|[*C5 5 [55H5u54w0̵Zϥ5ǒ6' 656$5X 6JX6&6:T66eO576(p66@6{6=6U 5)ٴ(o鴩F%Vy4 6Dx6s64w6K5S4E\ 46I565T 6y66 (6ŌR6#Ғ6݌6g6{66Y6_6' 6O5hh5p"6 86Y6g6vX6466676~p6ľ5X.xqdܵ# k77oε1l:2Ĵ)5vJ3g.5a4E&5 A5ADsrm~aAw*cOBГQtJ ,"Q_ c3۵3˵!} 4l_3r=3r4Ҭ4|t55֋S5566 6!r65T4_ߢ4`y5e6W6W6>666UN69i6@6 6g5Fo5Z4Ex8=͵Nc!45p6Tj6cT\6n\6}53d^\Uص Ux %ֳC586-u5We504:'oG#;!̴3A;G6ҵ["YD&εSQhB5G=3I(~^ l c¨Pӵ Q74Ϋ4VTv 'T5F5bʵ+M?G826/09cC)4e54uʴBRxwɵd*aM3\,:ǯ+/>XH֕:OoH[ v5t`N~Kn|uK'օ5o QThS =T%3M޵Q5'd mȵs, bF񲘴UXB5W55'q4*cZ/յ܃ҋG3#555]m.6Kl6]6<6*6lV65WKxUWnlݕ\ڍQ1Wj4B!;2R7pfƇqcJ 5+55U5'i5(5/ɿ5X5j5S 6_6>` 6D &6 6|5{D5 r4g}pzp4ƵDU4?4-0̓/Yݵۆvm崟'5 G544H*4f5҇6y 6$6506>96U6W44R5g=5$6;655Ai4hiKYK<5*]66Y6q6l46k6x6Ѱ66[{6w;6N.6O62(6n6l565.55p56h6V66, 666+;60965:6dR6?6D66җ5v[55P5 5l_5mz5.64)65a568R-6o6f5 515̹56dG6i6t6B5w6!6➠6R:k656s5G>515*d5^56<;5B6PR!6nQ6S6~66PU6pU6! 5``RYcẃz⵬=Lo:T! .4!B44]4ݘZ5u5( 6Y06:S6&6iE6_f6:B666 P6 6pX6I6ۮ66G616}6Z6VG6h6C7666G6X6lF6c6*62ڬ6qB6ј6~665ҍ6sԜ6N66E666וr6*6p6/6ց6?86ޯ 6a|5 )5+;5UӦ5362L666I 6686"6 6>K64066 U76(6)6EC6D46j6$}6ۭ~6MKL6F"6"55~6C5˦f42H5rt5566U=6՜Q6r-6*R6Ɍl66>6]c6?6$6H6X6dj6+;6z.6 6"65w55v55>Ř55̍586 P6~56%66595l5566H6J6*Z6(S68n6 66̄6XI6Y5%5 52}(2i\Z'*623,55-6"65 L5yK5|ɳ4fٴiIojpȵTصs^s34{&55֣6h\6;w6`6Ƭ66666o6)A6V6Bd_6L6{26/6c555666265֬!5\3(g4J 5sV556'6}>6>6O~363 66616z666@u6d6X O6_6Kv6l6F^6l 6ħ)5JW!@g䆵+55Y6φR6D6 6544XSN ~:ϴ`ԳH#5@56M6ɨ555p+5C54x\$\v^4&r4'|5b5!5uk5h5ӆ_5h855^ 4Y44݇5u^5 56j56F!6t65J5:5o44E@ഁ6ꨃ||8ֵ4 #-\};PA\|`.F׵l9rҵro]>ۃQjM9n+['.+G*s4c;556554? ˳ִ M]Z?56N6.66 /5S5^4 E45v! % |抵!4%S4i2*WΪ\BkqDs.4ZH^B[J?o$Q.gIBd?qahm\!EWzk%!9C#" *RiCϠ`h8E )R-exJF%'? nu4Mh4iC53M)5+w5qS%4<355Q534ɳh-3vI`-䵎t@yK+m cU3CzCRQg ^/@|۵h.&i>3=4O5Ob!5ɁӴIP&E&\r,'UtU]y'Oa6z1PT5 V5O4ص4E-`Ab[e,R|N$ Hдm=ER(;*2d+5 56(55#>4k+$SB33H 355ޮ6'6n6\5Gc5g}5Tc4e,fkpg.P16CVŘ?-<9/Gj^> k?Y贽Ahoյ N^!0 _`Ƃ 5ŴLSEO8%rE{44 S4{z3>ͳF49555j6 '6io5>b5YV8.i2/55v.366] 6 5Nj6566.(66,6>6p;65Y54!x4^(5,5ic4@xʹK&< Odj,*%i2IW3o ɼ:I 9JzSZP@^L5z煵!_>)3H®55L5GBW~6 uT5.-413 ܌ϴ0M\4 ʴA5D5 &6e6Ss6߇K6(q6{6OC6F6O6]6 p6Ju66l&6͟6˃6HLL6'6'5ڤ5H?5I-lDnmlmOqh22 4(q|)~S55m5l5Z5P5)-4["䴛@TD'4j5o5 6j*6؂66Fg6x6066G"66S6G6n655S65%6@6cJ60K6=f6:k6;j6TJ6$6`u655}k5Ο5|5W5B15ʉ 6=65V)5FMF44R'[556S6xѨ5`534555C55V556g5#&95 >4555 55"5 ,6=@6׌_6F6D65t5.55)6]661'66m6Ux6c5D55e[4J55 6o6$2U6Y6E66=V5˼55֝5Ҿ55PC"6b+65a5:5d25[͐55g6{v6v555?59'5b"5K?'36ƞbh5Li6}M6ρ66ԕ6{G6z6A6Y>66u5`6M-6FZ6OL6Q6ap6a66g6;q66Wj6fg6%6(6U66b6O66m666i6 &6?G6ls6D{666n6Ls6X6s96\e6s66>b6l6E6g%6535 6f55D5k#-5ȫ5\5N6=6:167<6766<%636H6a6LM6gj6hX6(L66p6%6%E6\66z866j6B 6r6.6\6c6'l6i6!)6{556!60a67!r6d6U36B"5x5m595}G5!6s?6|M6[6V6A6q)465`]{!ybt y6o%45`5/.54FzYG1սizrjh[44ݾ5φ55FG!66b6*6t5VI5w5e%j55… **4+5R6#v6Ր66?6P{>6J60b6 i6\m86$26 -66SF6\66H?6=6Q6$666z6}66L'66C6`5|~5$5,W5M6t 6S655իw5`5'6ՔQ6ZY\6'65F/5+4$q{i-GSs443W4Z5S5XS6566C6}%6 46 6R6S59/55556]5ne}5}4ĸش5 9585Q}5a443 ›jfS42US5655ց5y5Gp5n43sj rc0Ɇnm^2pG8h`]{jM2em%9z8|K_umOH|o/4D855o5#5q5]5夂4̵F 1,7N` KgˈX۴^9}Ҋ3L555[5'5]55G5*51t5k3 b ߩutH3B:5GI595I@5<5X=kE50 +ܘȅVg%{qy5T4!4I +"ϵNx:µO[aѵ_R o?e106|r/ 5,5}5Z'q5o5jr5,55Kk5Ғ4ܴ-µԴ K5255Z׵. 9!o=(; aݴ|"W:[,4[45w 0Ïssl-}kCtOI3_X [t415d6|.6ύ6P6W6} 6 5p4w|3y0[4 v44܁5-5.5 5J;5FM5j414E4k#_3i/[]tb0%ԩ_355EUQ*=YZ~)ˊJ\iR̵}؂r CҳƖqZ<Ͼ 5CY5"l6N-=6 X6?J6o 65d3}x8W5ɂ5ڠ55R55TTDJ#~%%%M~4hF5y5Dv5W5z6B6;q56:5l5Y5K5o55NG3JY3wXy5A<|~T$0%/?#@ G V$Jݠ<ߵ+ȵ.[fRƽ?^RliJ/2XtM&CKbT~ճ 5s5q5%45u55{6 665c5u5HO5M5ޔ5å596wZ6^X6iS6S6M\6ߢ55]35J 4y|"򭫵q&nX5T55v55;5,5y5J5,55_b5t56Z5475"5 666555{5W5Ur6z55B[5s55E 55*~514Z gMQre` *RӳM?4|5!66;5F412-4w?55555Do551b5JK51j5Z\5!5:5455Q 5,4c3q44GĎ $M=NL#³>5E5q5e5a5h4{u?{UQQﳇ%55h56m 6U6R67653w54"kݴl L4 Y4qW@44GI5555JN53HVSN3М5Ү55e5g5b5R526r55#X5 i5ؠ44^5>/53Vި( QVSc~ԴL5Cf5]5v575(4~?lf+Z*c}biH#s&4n5[5('565o@5*Gu%Iv直ʹ~ Y+`MVGҵ)ي֭24c=55;y5mm5!!5%4jWH53^#|Zӵ;93(55'm54 _k6V\0%昴{<12+4~fi)j+3x4P4`5aһ5}| 6}5B54=uݵҽ fN5kI55)6^6x6y[6Br6d52ɰ5I5(6a:676G265I1x5ߙ5|c75q55|64)6I=6xR6e66!w5 3Xqش&JN"9ʵISy4U5֍5~3yմ103c5~@5L55߽55 5R66P655L5!55|I5M$5+5ŗ#5555gj540y)Yq4a5H36O6A665٨3BIs,4/>44,ᰴ$4 9=^TJI c$K𡴆_1-AH0 M5_5n!5~6@8625.5mEwy_4c.5J5Og55']54mwJ2s<4+5c34}[3 3_4vˁ+sqU845qҿ4*3Nd{06G(6$5z505rM(S@ș ~4/44* 5i4[3HDr?LTK1K@*Ƶ?5T˵AtD.9cƀ3zV4n55xwʴfZt;3.C424#3+ .F4Hz*5 55?55Wv5)y5576b]6s6p5Nj5ZF5w5{4$A5:4U5/ 5 5585 _49 2c4f4xN4ޔ4m$424/"[4;5w5?/5 `4V5#2Q 54R-84[542 _5s5A05ԙ5 4s5G5i5W5Vb5- 5D4 45 5n w55x:L5U5Wʵmݴ49S5G|55TY5L6H6-%6M*6J36<6ѡ655ɽ4=Ⴔ&&UT5{55Hp5k5v5b5*_555hu54魂 S7̴Iu7qA115<^B5L5/524ą13B`G5y5B5̫5hf5E\Wd i43(5cȘ5&^5z55(5ɚ5Ѝ5555r6߬=6Q6Wt6+Ud665555Qt5 445155 5U5+]5S51h5պ5A5y5g*5G$'ɴ9D3.35ɚ55R R5ƴDmͫ{(/?)   ެpInJpRYTwNUa嵊bյdH425555R 35.4$3XX4䢴v[#~33EkMaki@ ˱rE44$55515[4P5}δA 9ﵜ&"kBS.9f^AfLK;1Uaxε i t(q?l%Ƶ,ŽbD 2BPEHuCi ݵ;浚$J صKʥ4XPě'I4f4T4A 5H4l5"^'4Ѡ5?ޡµwEGiE4}y\54 4^23˽$1#ֵQĵ$rc򫀵xGʴK4mpE"[j?].& cDY)鵓յĒWW-_5KbQ˶4^4޴V{r]v۵-FCDA8/Q)%Kf  MõL; ݳ4!1TZ,M#@={+Yu ŶY{`aH9܎|!ާ͵V iEs%-IM-qʵƵJ޵i>ޤ9iǵ)%60`΃Ns,觵WoF&VJ' VzYɵS pdv d o$x44٪ۤM]y(ҵ`8H;T zT"7z9 ҙڵ}XֵWF $/8>%}r Ƶص񖵔U̵7CC[AM-KFiܵyGAz/Pd2 B3l< ƴꉐ 4R'Y4kb4+{M(S1lõmj2PU aMI+N G}cQ_Igp3/3$q$/Vܵrè%빵l!F4V,495@5.5>5߹5^5ir4|4*33$`4hY5:vy595z3,W6_/cz.q3834y1$D3Հ9555#P5 O5P*5o3 _555 6 -6.6s 6hJ 6 65B5%a5]5L545*6 5d(|x;ᱵ8*^ϲ 0K?A9[ED6º$fX3t7km۵z6IY%vεõ pPֵd,Q7[E\gjfedV+ iFI ["ʵ- / ŵUڕnt~rd鯵ѥgo#((LcRM0U-isl=8>r5]AUd+@@= 33 G|PI"ݹ Ͱ+Wg Ef5Uv5a%55Vȁ5 5C5,_`5޵R\7;~B紇IZB ŴKTdP_U5_qЯ#CߴF{;޻̕ej"ݵµ Y; S\pO3´?6Ŵ4b"%`({(Ԋc]{qp~lwH-G- P3~843qbq:&) f|;ʩfT+.8䵁/Ƶl뱵F3崮>,~3ﵝc-ᬵ;[D.355m L5Of4g44s(KbggIPj;4Nd55p55oj5n5P5*{51 4#4Jg4z.5U5 5I5q54ٮN4Z'*YfpQ]WQĴGeloJn@ߵ{ls#C@ )7xs[{еcҵ&8@ѵ V/yE爵ڋ1 SX5y@䒵K@jfX+*융w|/8}{Ŵ~Y贩;#gkJJth1n^f(ŵ=ȵ>Ԍ :L>_¨3S;tΛ 8u 贌4m:qI,4ׅ?H6K'_ ߳y n!>S JrEƵصT͵m8؍33}4"wY齑\2f4/!5{Nت2˴ ?z4o4T4XqK4u;ح2㛴uKrĴNӴG;r̡r˵{\ά̵y@n+!?`253Xp_:S_<I4 155Z5:g5%O5zO54/3s`46K[-a:aBWfې44e=3^45 56~4 cA{h+(=1Dڳ=`̴( F3Q|\ʎtXҵ䵳ߵ =_pĵ˵1³xϵEӵµg N r AMtVhEz֪dW8d2Kf3('#/Jpk*wA|Xl{%I*DQnv:hMGAy6K.,}=*A~`ls .cUp%:bo&)hO逵蘵X ]#{U֬f%׵" !ܚ h资ٵڵf/h+tص嵥[̵C&m}Ǵ^baFE>rf.;\,g|3ڕ2A4"fK5ط5b5 5/5E5Y4DS<3px,4H8/2[3Q~clg!Os洰= ֢27^}U͈,7h̵쟵 ~6bP}WFf#E/Y3T\ε,ĵ$E_<T4:55Sw5046 4ej'7c1lsW4'$5i5%G5K5}5q4L5ow(5WE5р5u5\5(4B4R4ζ3S#䬱p3=0-5i5Ï5?Μ5c 5ݳ5&LI3]47(R5{25zY5U5V5ne5H;f5N44z?d(г(3j4255nb54c&53']F(Ѵ?A\:jv1^,#`m@脵СTDAx[;6B~ 4z{%ư893,_<~ Q6;#4O4+4gGU5?55#X5+5gS5x5Y55٣55#]5i55)a5C5wu5s50sp5i4eԇ4a4X-@4ѡ 5eT%5w[5v=-5h~55cR5(5ڐ5T5[I5ij5Y5)k5Gq<57=5N9Xrh0rou8St4R{;)Y~" UִE>4 aC4_x2t5BK峎 @e[C4?)45j5V5A5442i4O84S4ZNŴ͛ \4m405l5c55LO5w5<8#5hJ44]*O2#Tr4F]i4K4 5vUv565B545O!3->#`ԴNo qĴA5LGG5eG5&4%4kZ4fN4xr4 d5lWI54-{ka4n\m4I`4P44`55n^5u#5 555k5 5m55E5BZ5Ë55K#5]T5k5 5D5_5ҹ5cL5OM5)5>[4dسE4OrwXK+445`5+Ï55o5I5~5UL55L5)54j5[i5щ555w5%5RXR5exL1g87"ȭ0.C/_봃,nF$V_t XPו2`$´*DO} 7٢N 044uD(5u5ڞ\5>47 54/44E4\>'k2r Aѳ44m5#5Z4W4444l4ڞ44,K<5Y4+3B 33F323V1555]5}/5bd493´YOD̦蜵Z9w41@5u=5(H5ٗ5F5ML5̱"Ĵq&7n!i45ь55Cb<55NQ1ͬ5\+5&9S55DR5 N5f75u3ԈKɴeA'dŴJLjU46䲎 4AH8#Z"CpδCeF4"4F4l4w4P4m44!4G2ܷUd۵agd@XDt"eBs%ԝz093\3 #Q@zGm" ؼ1ؗ4 !553\%5(53IѴT&^ȴ4~/!*Z,-j-/'Umخ!{2ޱ>' e"z޳ͣ3h}L2-?nz}Z9nU:Iy@l2I4 374B3 XZ/&wW! 5m6͙4ng5j _54<44P4%4f3]4F5!æ4'4e4 Pf3ƴ3v245M5k5[55M 6u 6.6%5<55,5䉋5ȯ5085y5Ӈ5t5|\5W65"5? 3l~tS&q= #4i$4e43-FewA^Y׳<&Y4 233-Kk/3)ҳnI$:6l,^ ݚw-ן84jI5Hu5 5d5`eu5ՠ5/ح555JO5r+57-5cM4~>r% 4w4`4>4:4+~h5`Y5Y4N5N i5,5Da5ʝ4Q4m4R-414I4Q~55 4\3b4! SFr UKTO*fsį&?xGu`:+ 36JߴT$ 3ƴAѴpkLD4G;4!4~4 4jlP4+54<55.4~Du57;4J5/A555WV5i55U53 2)Z524AT&4R3kų_ "[xh?bohp4 444"54!4س锴<Jpg4d޳jH7Ok[3244@34⨜F=2==4Zy1dW4 5%Z5+NT5]5Y515|5PW5>5h75.5{,5a3I5OM34s4v3E354F41Բf5_4S2 5#4+US5Մ5@5(55#5c55­5ض575eH5t555ЈT5E1`5w~5k55r5X555އ5Ѡ)5mwY5;M5Ϟ/5cЍ5g5i5 x555Y515K5:5*5X5%g5C5kZ5'5b5.5O5g5#v5K!5a53555̖5qؿ5ax[5E5#55(5f5"`n5l5WB5g5I5\7555N5P5LV5 55GZC5 5#5R565ζ555/5О5ӽj5r5'55v5x55H_5|50T57P5\#55J,555t55Ó5#v55΋C5i $54q+5%*4w4S4H5? 5@4r 4145G3555B5y%5IS15]l5Yj525]5 5F5p5L5255G5U5j1R55{d!4/5 5<5}5||5YZ5yP5o5G5*5q5#525|.5"=5*5 55>_W5#4ZH4C44Vc4 Q5[)551554F_5>4tl4J4m)34 459vq5s5V~5֓5%5鞨5⚓56h5475~E5h<_5mi5)+5 a5:5R5y~5ȁ5(a5s05QO5g5gL5{556H565Q5555톻5SM5Ⱦ556 6l5>5+5Y5515\5t565;J5vQ5B5i:55? 55ͯ\5b5 }4r535u525$q5C5º5.6Y5t5}55Pc56235<4d44W5G[5!05_ 53oD64-3475d5T~5'E5b5A4$54-4LF5U155@5j?5抍55555A5ꖺ5F`5] 55[ 6] 66ە66m55615&53[5P 515w54P5744O5495|E415<:5) F6dٴ5T4oej4*4{F55 5#Ce5u/5j_5/95&M5ڮ4(3%;3 K4ßE5Z43f4IL55}5b5~)5 5{W544t5:4〠5(52{58S5Ʒu5/K5W5G5YBK5i5=b95K4m+_̴ vvش 2Ʊ4?4{4f44%4F4z:5@M5,55[5j459h4>2ܑ}4B\5 n5݇5ő5955j55r55d 5[5ń4U04\%7OU$4lbW4g;44wS!4CO`Bz@L6䴠K_I'2kұK1z˵y朵ٍҫA'KNRiQt Iҏ=NU.A$=~m=a ($δt!C475_4Ӓ4z 4i4~B4酳dWX3d:E3}Iำ4y43ch4P4ﵼ44G+5/5>55 5Ҧ,5 x5|+54`5AJe54m*554oL3VێL3 ⳮžR*epϤ+߳4 +3rS=\_ovy{d[ґ]ٴѴ%)t4vI4ef4<4q= 5#Ȯ4ъ3ǵ4~4"?4gK4?Ka55?54-55B5b4o4>84J084#4!3гiC /P8-ד47 v´< -D4Z}47X%bZ>bLt|+[۝&ش񷆴w5@C;dzR)ٴ4+ێԑ+H)4V49"5d347 aɭ4c4t5[25 4544$5_5a5E5a5 54*45+?<5t5y5v5Xs55=f5ټ[5.146J%4)ȴL=R5w3X4f65.44'ۨ,E4X3|!4%ڳh3Qw3[]12Cn sknB=~ eٴ4In2ㅳ9u 4`@xv3145 1lᛴ0E444b[3'Ӯ4V\_4X6+5ݬJ5Q5\443Λ#S,e553M5a5M5$5dž5s5A,54G:Rȳc?u8$B0δeCԴ@e4-+43eδן 1%fej9b˅ߴɻEqR ~(oҭC>"5Z4(4{J3_ʴ,n?C[415v5 5Z1445%04-f5x5Uo5CC5;O545 4k5'4Yfzaj). 9ih,RѲ tkS474RH+6 4Ai>5_*Ks׀U+q474>BY 0L-P&{d ,->4뫲4@?4mT#5=5IS5;4%3= 4:v72E 4W4K5405 55 <5-555$5}5 5A5_z55H5e5u5k5Ic5,4555/5455)5Ң55;g5Ӑ5d3ij4K 5H2d]N,4;W44й44=4=4y]5|4e5QM5B4̪|e4㠴YW3Ո4o5yj5|o5۴55@555l5{!t5n+q5aM5#54z5R05n85'5[=595M5P55>5@5zI5~C55\5B5X44-4 4+,5f4@5Q5ɘ5x5mh5)&@5)5 4mH55/45^4 4f4z405o4H>5X$5]5 u55yBX5g5ǖ5B5!_5rn5i+U5[#5c#<5k5*5555:5ؾ5N5D5z5k_655º5׌5w55&95)5+_5Y55535|Yx5h)5cv5͙44_5-vu5Y5555R5DK5˧5%5T5#f55/5TǪ5Eɕ5?Ǣ5&5Q5k5f5)5N5:55^585^6G}6_~66 6Nk65f6|5i5#J5{5[55555$8"6e6q 6b65S5Wu55g5V~5{5N"Z5_V5'؅5<-5Y5C555 5A55疇5UO5\"5 451#5 T5Wݗ5qs5j"5uW5^<5M44H4A4I5O5k555555!5J^5j55% j5<555ag5#5 5\4t4A5465a555Ӯ56b5}4_Y525)555/ǯ5-u55=6=555G55b5߁5}55Z-5;505HӋ5M55|`+5yb5i5]5D55575uG5Z5U5'I4ί5E5#y5߷r5M5T5wV5p55;5$5?5n5585]ٷ55 5 5\575<5Qo55}5595552h5VT5Vc95 F56=4Қ 54~5L5!5_505\/5`h44Y+4`_v 3 345=,4@4s4A5255:5X5;55jU*4)5{dp3%p\32 5e3rՀbh4d4?4 5 53WM4k4nZ̴ѧ}֠44%4qP^5QS55$5W_44ƪ-5~-4*h4Ozo'/紨np2܋45dv5j_55Ƥ4h,5I15~ 5X4)j45,O54J>4:65_Zĵ1ZA`5U4K%4w 55i44QH554ZO4nv4/ 474(4^@5zL5U5L55Į5fQ5،5E5m*5\N5GӋ5375Jqy5L5%5YR5٬5D5m557a53%/5bL4i55YG5O5U5gS2r43z΀N[l7 \F3?FDk*D]OuC➐3kc^X>;1TyTΖjp\BS:q'!ߴ% 44!3CO4r#&l蕎"F?3FL4#4t~4Ww45!4/4)3B RM!&1bm p4L߳j1-34'4S14Hb443-4||boW=4Ӵd|ܴ(4\޴ #o7 ei4(4 4ڤڪറR `* CA2a4r43 55 v5T/4P[36t̡;˳v{ij784Z3 '2U|룴DNPxŴz߉%%sﴭM8SQδScRN-n4G|ǓS<312Uc:ٴă(`9pɞFɵP{9G~Ey[b&̴&"M>ɐ"D0K]TVlڵthJW*f*ρj%OS)4g҈Bf n ˳Oa[ hȱI4FM6p t0H/eր?µhmBd*cX*;Tnչڴl=>6m?" :]'4S4Sd`1^HDDlϐ봭;j3h|3q3Qx44!z4+ JNFyi/2<0vءu4o&4)4#4j4>x%540*5f34;3F"4`&44M44,3 #-44!3m'4b54/4OY3} %춴]vm?GA'I̊7FfBDɄ%DEa"g\5$E3壴3E45M 2[5{J;Ir4Ks4|/5 44+51 5.4Z4..뻻(Lֈ:"Un˴fijWT44u R)3״ C#wV!ߴbo3o324L3XG44:44*3?4q5w5˖EWm*KҸSqX4 4*3@4TI544~4 4L4H5(4^x4g&[ų1ІQ244XM4d5d 655X<4R,4G}" &4n!شO l6Z3텮44CxMK&s52:5R 535o5BH5 P43 f#znдSȴ쳲D4se2g4ѳ J!M G=UkN đ֎5}Kw?RƳxnֳӲ*ar8ikҴ] 4"߳+3[۳Ȳj4q45445.T5P544=K~3ӳ88;*ǀ)/s剳'@ٴv=-ʛ4W؛4 ?4c3_(B}CٴB9NX 3oq4^4'4Y4ip 3v!]Mp1ppLސG3Ϸ鳈R%4Vz]4UW @#1 &YYC/yy܉#;8f峁d4՛1H3:T4u5A43C"5(4F54kz4?&4w4#5(5:`)5r4J25d55 4i5A4"4;W%4+Ff*;E@ߴ3@ڲc3)3ܫ2:yuvE|IX́_Sܺ929BW4ߢ5m4ɶ 5l'5844#54!2X#4dv35455|N5G56v55;5h5i\5"ъ5#5C5`5?e5^u55 &M5Y4'54.% 5\5;5 5l/5~5~>4VN4FX34,44-4*4b4pՅ-4崻} fi3gR444r`N ;9]v?4+m43|4zm44w$C2Ra]V]v' 9/+"=mĴ_ .%ZW%Gsc & 4L33tt?3HAECfŴv*2c2ɻ4Z38#dTA4ӄ]D7C (^frl^2y_Wa!)LV|ER؎& hx p9BH ˔]1󉊴ؠQk촎4$x84ޙ 5\>4fG4W41qD (#t2鴹Lk>{\۴aTzn3!E,ꊵ=Q~VEAE'z=\*3V#1_Ì[B\Klje%^1pZvO|404~w48'_k3Հ3(˴vS9D$شM1ȴYʹbYL7QO> 4944-Jƴ,7& U‘ 3!498,4w2&="fD3s"4s4F3Ϸ3h4q5 5jhE5pHN5.765?534:5'+4474N"B3_3yN44ҡH4o3´NgFQ<an)FO'l[ro!3t1^铵9Hdw؉N]2 *trDz(ݱ4QHI Z=`x3}1 4Sb40r4V4j4K[314e4$5K 5,4У 4Rʳe\X4Nz[42""؞(3J3D.e=:364%1i54;pԴm8hдHᘴ Mb4]׎,ʳ _¡c~,qz?oֳFbѳj1ڴp31⭴.p4ԋkBE3Ktc4f4v|p+74wK<鳄A\4V4Ʉ44j 2Ej3cSԴP)3tj43[o4 !2iG==4+4h2* (4A4)v4ؕ45*4W@33K$384j:24&7O<44>}44e!3클,u__Y4fz3_ W4LRR23:444 N 3Ws4[43`g35p ^ŴO .dzlOq454q4ĬɴJɶuOLBhȴ$plXqشZĴ-3AHSDCBv,KNeDB`۴MfàB0T@o_\ ]<6 GIdQWtAck!j^hHi37@41V .nrtX1Hñıq啵 -}75 fJ&rvXF9Jδی2*  B#1<´>2469>øD,nm0j6ȡu@*//>vrٳ(ƒb l8:A ִSoa 1+Ŏ#g3s44:m4Ng,3%1%^cCIp9gҴV,5K${Ϊlnp#?3H$7ô#HL_ŴPѴ`A fZִ(#ᴋo344aϦ{5^$4@44%͚R'Ӵh3;2!4d654q4$4V4)N3]3%42A4$3~3j2.4H4:4 4ν4 wI44Ay54|&5t4,455noR55F5jT5[5-85`E5555t_/4N4(" Y&em3Gŗib44Zg3/b4Fn3ƴ"X/$cC0 spHߴ&$13f4?3N"O[k4GWy1lح3u!4Rmβ4Z4hO5474Q`V?Q[u><X8ܴ3?Q+Ե(<\@ P:t1˴46h؝ w"斵8^fN36/ᴨ uo b!FIl`eЀôJJ7Ŵ%꘴ SG0 )"<4A2NI4L05Zt344BbL49v *;1"W3+}g?41Z44 +4T'4C4S4ih@g *k;%Ԋͳnij̞7>ݳi4̴nѨV,&մnI ִC۴!4@e>51qТ4]پ35wi4mA0ȴޣi^9@4?㳻*Bdq4q^3 R33<Ѳ3;A\/3 4၈ZųJ~.]3n4Hp4x4A4ަ4;)2bg4 xC+ִ6a.$yx$"Nӳд˴E,m.b3h4fY?.nևδ66=2%ʹZ!^@4~843^7{|1mNm3.4ڴ7{4n~C)~)lH5wFY޼V"ZM[Fe켉Ɔ4AW\jǙtd֭ʲRhz6Aa›]C]~48RՑaݴwKȴ غe !ҺW.BpNdz<$z3R(, 9e2+]4_d34yj3 O'+ٰؐ!!"ϴsqS3T|4V3ټz&483y˳=-0GtMN,a\3{AҴ(åĽ `Lo8kgcLIvDW+jTYDRɊɗwfؖA"(\6&m7*}|G&z2hCOhU:Ps+30 /$ô!Tڳ Zo1] _3Ձ3bo &ep63(B4[#5C@44F4v41 4x4 3`m´7E A횴b4md2ys4+0eT4뇽2>FN2"Z@lld5!3NƲ͙3ZOV24U4HBi4B4g3gSF14s2R$J]{)U44ΗF45mn5p5ʤ_595#>5%5T3VADNK2ME4k44s3\24I4b4~h4D6@2hxuҴ҇462qWRYM>342 6%"444$YI6N:4+4Z/"Y  ' 2TL4FrX4"[4L/i>3Gˆ 3+4k[4,hqd3%'$2[uF4dW4"44k4݂m5?hB5FP5NI5v@55dz`b3W5lδ5;0O̳Nm4`4w4(&5-46~ 5݉4$44ĉ}ɴhn4h4€4}44?5525h4W4, 4834Ů48B5G;CD];p3 {d?4a@2<-;cvE&#zo Aɴ~a!;t3(43&bP2;!4wݲU33q4ޥ4܉8rz4E 3(!044(5z5y@ 5x 5}5q543@43444`54-2Y4544t554R4h42#4cg$t4{A44''"545)5=F55S5ފ5Y4rk4[4b4v4=R3:4Hr4344Z$5SA/5V5Lo55!4Ě4u4N4Ms4}QDt3a[4y^,4` 5/5}4k 4H"~442گ4p44BE;4g4,4n8J54MU3!5YXi48!y44k44@3q;\1^3?P'=4~4m2g3_2홴䳴Ɠ(11b3# ?p|ڸ3j4]<)4~4aһ4$,42555M5(65l41*85'y 50<5p5R52Z5a5^A5-d4a4⋐435643=24+=c4`M45{%5@v44%4%o3CmԼAuSx&2<44 ]54?$N5 5M4i4NiFyxT$`v1ȼcaT5$5q54~4&;4443524w`nO2:4 "5e54 4, 4h4,4V945a42$5Z)434Cc@t~hH(f4|C4[\;5t3 4E+'gw ‚N  pl_D)2ʴg`sKA;r``޴+@Ê;cb L)q@G-8}Oo4&lۉ1{$49` #W3a(Jv!zi4aJFv3k4h3g+k|C444Bs4\w4d4Wt9+!?T"SXwu*.)/3g4T>9VdncdAʼ|fn6^@^S{"^DŽXtj6X1eG δe8 tgw˵3q7u õ(Ƶ,Zrɵ?ĵԵr`P{J(ռxbXQnfud=nH J.Rem9䴕;yIO\ȡwf l OfjqiDwAEK5z R,'h#5~!~ U*ďT IR;4냵6Ե垵2ǵx5(c9⼵;w4ֵe\Dna羵>޵dfѭNε㶵rY0Gj4}5njNi)\@.vaoxXv1V 卵|ӴxGg`/hjLP玵ﴵ5Tߵǔ%{G_صa ѵ,9M׀q>(. Z3ϵAȵ ﵓuݵٵ(V$˩jŵ~+@pSAc^抜Wu @t~(upEfs͢aZ)gq!79y^񃵐–#z᧖nTԵ,ݵ=޵$5{튵`p#Bȵ3iŵ9յ޵[$ƶʵQɶg>׵ΐrO6Jf!ҾN!1HrK`󧽵v8`R!z|d8Z^_-84o/U,vcvMJ;$Z{6 /D;ױFÊWsfLC5fExa ":UIԀYhlOC b0\y>csOM]lQנGBU m@Ƃ:$bg0 ̍?"#?ŁѴ<2+PȴHش.w[ZVIⴄgg D| oKr]@hcM,%l6i(ִhI4;Z칂Tagi'㾴Q*FDwܤ7촂'1`A&j)vNq44*`4jDҗ3Y: <7o^z^KSV1ÿ3j۲cF3n49}yyZO. (PFCΐ3=I 97ŴD3b!ݔ5r<*3n|3Z3x 242f+4j4{C374Il4ۓ3N4C[4Lq2 '42kaᲦW:{ظoz3pCwQ4fݳ_Y(1ⴤ*͗634~R3u4_55Ͽ495w4.645544(\;M}'2/4 627m4.a:II4:3]4S㞴^꺴2ѪG5>Nf`)4}m42)h3Դp賔r ^HK?(-Ɣ!"d"ZkM 㛴ȕ8*u9-&/ź4kǽlZt4,43<;4U=4T݋4i74xmb44я4׶4;3?4G394塗4434zW4ڄ5É5oBz5ju5O>54*(r4;4Z3V4Sfo1N3l4jZ3TR43O4|Ro34&r58w23[]ce44X<44Mp4'| 4k43[R23Ѽ4;45MK4H L5gp5aX5ڨ4 53G54a5A444$4 v{5Y4S5t852R55'5S055nH5`4!A52t5555Ɋ55u5g5t5b553q5㽈5u5(\5u55|5c[5ri5,"5^4H5a4,5 64v4`4z3b3IK4 ]ɘ4A43\4hv4Z4{4a4944Hv 5>4X;5(95e4g5zW5,5\؝55@V5AW051~5-=k54P5A5J 5Ln5m55_5l>5gi5OЛ535^55Or4p?5X3ʩ44'4P4uE5M5 4} g5c:5E\5a5484R54E44 4X;5Wi75`585Ws5 5b44w435K54j!4D$5o4r4զ5"5@55}Z5F*5y5 _5(E4Qb5BT5/U5w5S:5]&5kj5ix5_[5p45ZE5455?5EB5[5}!^5;s5J5=)5tx752-5"5j5g;5[<5Ի_5V5ʉ5&5D,53*5ә5=5s5+5&15g 5V5;5w5}4)̣3O=5w5BR=5`5m5{5P551-5{C5 x5jF555s55yz5Ф5u55ʥd5# 59;5۹5o5av5'M5 55k5({5K5M5޹5555s5e595_d5|ֺ55k5e5/5N5z5蚣5k5n5 55=5#5ð5[[545A5$h5jd5أ5L5]5.555;5255/5ǟ5+~5l"5+5!5K5K555 "445CZ5 5P5{5!\50s5)<5"L5J5+55՟95= 504e3J4%4P{4;1*594"6)5E5A5f?5?5Q5:5r43\<5+*5B5$%L5 i50}5d!5w2550~5M-55.5o5%5{5d555+,w5EH5c?5E5ub55B55G5s51G5H5Œ5S5 N55485PW5w45 4ЂL5o5=15<#54=ΐ5=#5f5>>5&5;55_55;4˗4&545'5*4j49T4[4*4;4P>4WŁ3*q4> 4 5[445D5e5@44"5V5#5Q!5n4c4Qf5S5)'4Fm5:544H`5A+5_B5? 5>554yQ15a5565N5rY5 5C4554f>4ʯ44,4fy5w55ah44|4745̘3J4v3O4Ҁj3 G4U(44̚3j41v^z4hh^4')444$3}4#43?4)36s1c=1J4| 4|4ץ3C)4\44A4. 433<8VSڶ0/444w5ڎ4F4}4juO4 3>Uڨ42F4"zL44P/4vI4m4*3bųѧV=2]4 Ϫ %Q5u 85>9x4m_'3h3j+4#4,4~U4>aQ4, 5z333ӎ4*s{YNM4Ǎ?E1 Sjk4ո4vg?ó"ô;HGƴ\ۭ˳3p4343ߐ4!_m4pL4!Cu4(,e:Nrij軴? 4KÖY⓲[4K44!,5$B4G47J1 UiC2WŴG !ba5]45!5z[5>5:`5Y 5u2W5)%I4>z4v|4l3Sqd4$4,5SR5zD 55R5X45ȂJ5`44 5 554#5q5.5Q#55h5<#5JT5jQ554 5kS4,4cz24V45<644O^4^P>h4ŴQ4da4E#4]4~64v?434ld4C3^a4*g4L#43j84|srf3g3Ù4343P3"U3_4M4ɞGBq4v[{B!xxڳ’da|n3i,Zf#K^Q4ܴ JӴGִյCBqt%紓Qub75ɴfqP"ִEC#*Hl^1Uf+]\Fp!~[ҁfzY!SȏE\I~d~BPDBJiɴZuƴrBWa2Q s|Ii3qh?$44x |4ǭ3Q_P4)2𴾭>.Wr40h ,j13#84(4=i4544G3JmZ40AmR44͇3JU4h4uCu4%r 5{644954Vx45IY44QD4u3B=3[v5oQ4f+54-4WL5T$5OC5+5kM5h5*QF5-Eu5W4Yw 5U4W4]C4E5S 5f4*>4K#555 4g44-48 4RX4S43!4341K1E3O4o4L4Q4p4y4\2U4R~4 4 4M405is31L|843L)34[5Y4ٗ4< 4^V1443d20T4n4 >{HKؘ&Bɼ?33)z2S3g2|)T г54ʲ.v괭 ޴M[ӣ+섴¸޲YO"3=3t3}wس03.g);S46Lʴm%ARR94SȴNbT`"k Xy rc?X޴RǴT좴&˴f+kJtoҨG4E434D4,A3,ay39M-n. H?2gaK4|4I5$O44'50)52L)39X3 354n45;W5oB54G:5VW5D545O424,n4]47˳WZm>44I͸4~V3Fx4)4p414(ٱ44934kK 54a54456l435{W5>5R.5$D57%5*u5E=555`558555xB5$5,?f5X5Qdh52~5}5ܤe5IS5<55&54gG5a[5Z5k$(5|4:=L5Q&5 5&5p5U3'555"4436454!43 5,4&44<4l= z 4/34R3ǣ4E,3=4;4d߳D5E4jucm]dTPGr4U3c4;4L4?4N4?5#455Kkl533K4}$P554405p5gi5{55vD5]=575F8535as5/5%j55S55m5_,5u5o5555l5 5) 5Zy5:5ux5d5'5WeG55'H5v&55 :5+5G]5w5|65)5Z5.x565ll)5aj5K+5525_Y5`C5fn*5o6\5ɕH5[5@5jm-5t5wV5 5S5.n5J@5ɱ5.f5X55tɟ5N55x505 5z5 5kbl5Ɵ5-53565!5n{{5x5 x55t5w_5ҏ555 4h5ZI5-]5v,4S54D45*5.5]4p548#5'I&5k5c5U\4`u54z555 _5ܨ5p5͎5G5?75뤬5Ќ5'f55Θ5߯5-:5N%55Y5C5\5!K5B5(¸5-\55~ԩ5%5@^5Xo5ҿ5/535ҥ5ՠ52Q5pGU5+֩5뭒5[/y5@65h654V@5n/5:;5A5.!5-5`5Ʊ755FKt5빊5qz5Vk5_5'h5n<5-f5#5Z]44,5|/5K5P4G4"A"5: 5&Q4f[3@4%/44D t43vճ 4ӌ425Z4 m44'44sή4 TK۫4Iw4?ط4f4:4|0595t5425c"54f44x4Z5(4ѳ44*+3H'O#>{4YJ( "l=33".Vcھ44ש34,A4?4jͳ6#3ᙌ49[3%1%>x4Bi34YtM5eɳ4aI44~34i4|44?b4BY4c4;34~i44&445E4r4(4v3d4}4W(3R414>4fijkО4H4}3L5T4f3¦433峯=44R4%*!5M2 R3{P4#.3O4N4nn35ݳqJ'_ 3>4_Kh-4m3Yw4gP3J`LCU3e3/1ެ}44y4OS2!224"3R 344\4a44Ȳ244S4aU4-4On4^44S244/3-4\?4ѝ4;3E3 3XJ1^kw337d|YR5&Eϔ u@Ǧho3y_إȴVW4uo(W3@(-p᯴츴2!5Ǵk3Sôc4UմЫҳ1߳X6tĴ`kгO7Dn-%Q/(W$n2462THM]4 .LlIfl}X䳽mCY`r-.>4Y̲9a[Z(Q11#WN˘\>!}CI0%\+흴D@(!s0>+la@MI'V% ޠԴg!+ʴrۿ'ٴT =:|@~ɴԉ#%Ĵ3f+>j:Jʀ]A 0K2 Nݴ6ߴE1дJ'̴(<ϴtCLw!3=B2ۗHȴ,a3{X\3Z{4(.ڴL<A 93XCQX4xus<4سL43W<5WƴY "",!3^%a`>r !*@Pf:VJ6I-T*DgIWJ!R_H/.(7hJ9jm BiAYӳd.޴hk1V 9ȴg7(zu%+9-<]OE+38^hy&Vn5LQhg# N/!+T2ô<0_/ nj!3)3*:詴 &Eh<&׺ 6]/_wwдpb"K%vʴaG`U/cᴼc6t~EϴԌʴ*9)L4 h/ke u3R 34& 24n(4Q444743ĵ4,4K?4ts44Px 5L4ۭE5Y.5w.5O5-5425Sj4R34594565C5 54t524W_5641(5[n5s>5J5W44 5^34}5wv4.O44y_54 5F*D5S!5$5W485cJ5e5#y3@83l͘4xk33C3C4=,4A4Q]4S44+4щ85i #5F585.P5v5 4e15J594(`y4o1*54XZX4U4-d4 5[(5AH54kh5jH55? 7595=45T5P4KW4/5)P/5?.4+ 50g55G5/5u5\X5~5M5[5+5Ha5p5U 55o4z40NX44*C54N5B5o\5Wk5ۮV5OA5Da4D'54C4&;5x=:5i 5=Gn5I5m;657W5s5aF5OC58d5?}5.5'Y5u)O50U5t#15b4Z5{^"4A4W#5&5*\5}@5$5M~5fj5x\5o5e855V*5\5)5LR5&n4ہ5*7g5Nڈ5ǿ5;5s525O5E5at}55k:55%55j=B5dX5@dH5C?5ҖZ5%G55ϓ55Jx5u]5i'5pj54ה5#55xt5ܦ5d5kÔ55Eǘ505!;5*5rz55"545\5o5S?5xś5=5M\5Ag5_-55I]5n5555#5?5FB55r5iQm5/5'?55c555fڗ55_?5v595m5ٷ5Ψ5}5k55{5 5ޟ|5r5Ĩ=5ϴ5O55*+O5X5,5OО5폈5N5]>5|w5ײ595.5z4:5e5܍5p05VL5c*5565χ5ǀi5'˹55l5T54 4N54C%5H55"5F5{p5D5Y!5Wc5PYW5<53K35#Zq5&595pm5w5k5R'w5v5t{5V5 m5k5y5Ofs5i'57>5l85 5`5& 5,Y5%Е55E5=5X15W=5;Z5bb5i 52S5k47!5O55)55554.5G D5j5(4ʬ25y4K4:Z 5=3©{4d[3&]4/;454 54z4>4yN!4(4&3\y4!4c<433' 4[>4j4N4sR44a4;6443{'4J4!4V!3H43]45H4a4?049ܓ4i1Eh4`3$4ʐH4С54R4p85l4 p4J$3]4-̎4z,4js4._3"3Qb(4gT3B3Mq%wѴ#R3?+wFbĴNdݴ`m377OV'’|S 鴲z(@f_kþ4QR/8QN4S64iUj-}W2MeP4e73'C4Y>e4t74Go 3 4y=43Ik304Pճj6辳c q4Mv24T2MHՒS'W#D3uݴ hj4ݴn>z(شZ\ X$$,4'4,ڳ44_4H]8tL4\v49dffBZ,>cR.g52Oͳ B=82Ve4C%Wx21)0m侀/VLϴn!x 2JSv3e=nr%47DQȴ.{Ӱl"F $՞<'XԒ-x87in1H[)_a}qMIj? :fSE T!44mp8##S y]/os:syU#+O*,tvxW&5A:\ X5F_^lh=?pLv2: _&ם>cpMBV<5jᴥ޴Fq-մ;FmCiB +UD ;[3@}ٴ`^E  Z#ت$VӴ+zČQmH\ٴ[iM6!`ôn̴ܼ b-HQ-4jG{=Hwʴ%k Ŕ4u /jr|´pѴⴳUԴ 0Ѵup S&Xⴻ*U(3: >X{P3y E:E1b'L%^߸o]h--Z+hZ08$wLT Qiv<0ZP,{Dk RP-H;CcgM y#ܸD[>51<5/R:m#]z!9/㴶6g,=9PTY$+Oɥii'bM!aO=\Bv@4$h%sdXfj_s;:x(o )%v>zˆ} bjC`J2uEa51e44F ǁr">4Y3DA2 ´ײ[d2}jA3\Y;jrW:M(%ʹ-n?Az++4b9R`$T*qyºzG3!Ƙ̝Pд1„!;ƻ~U_w4`R1 n5uOYa?K|ջ`K~>rB"/ϴj+u4P& 2V G.tbʴz ە='d^1 ƴ6C/3^f"W3wǒٴ5򴾻Ba'~!ƴ4f2 ?ȊfJ&2(:%]p6Wy$Ӵr%i ~۴i74VDw 'TƩ/_bA)' {= kEWew`ܕ74'nSִ( FA&x!3)֚#,Z10G\+8{Q;҂ڽfKv,1}==sӴFӴ9[A. 鴑],7Xge)Qyؙm!L_MOd̞#0MF\F-Vը>wWǴ !4PXƴF۳M(3r13EGwݰ|B54Եg1$,3l4ys4505C4I+3T3#0D38a3P)v49<ܘLÓȲT̈́!3ݴm\B@ٴ{*ٴ+ﴮ)OMAdu.So̬w۴Xδz겢>mJJu6k"+)lߴ5[2Ó*AS6$ci+΋ hM5tj+8^:2%x 豴jQ'\Bٴɡ/gpe4o/HTٴS´RBܳf=+gwAv2֕%c/-=3)2?.^\EK& &?5]ִO۾Dki=)ܴ߳,~HA BQEY2ѳǟ3+ Pd&b(|[ش̭*44xw_'T4M2R434+=3 54kKd44\4Xl4d+542x45o&244 34+ 4a4$J44k4Z+4iÆ485U25n4R˼4S5plX4a84b4;x4Z45>` 5FQ4nC44czVI2Ň3&"䠲]_4Q@Ə -tD{>#)Okk=e6{9F1*=*11.o轴5>0[ٴ֩6#!gSv olZ2A3*I ̮3mz;HU u 5苃4)m41h~;u4:4[3#KcGL2pSqB~IS qK7ǴjXvCW 3p;"Zsra 4HFǴJ Ӵ'a.B'+QE */{]e$ճ 2dA贂ôyT~ 쁲[LܴM5qM!_b_'#0wܴմ7Z9{XԴZE#hЎ5E0'5;ʣ)YY:AinTA4 ~4j3nKo `'mRÅʹi[v]%RI]/ &x:;zYJ @ ?tȴ!Oܴ+!.-KE 8m ÉD̴ሴ۳-ׂAzv d0о* q|{VPu..&״ӾKMʴ3E)LAA7^7o遵r縆3Sq[{ܢrnvZna~eГѷ< faT%D*d Qg^x!zfϛBaVLGtږ RiL쌵=&bеj.HHl5QM&щѠp9k|.U쌵vGLsIr~~F]Lyf0<@刵|9xJ'>{^ 𴜀"$t6tﶴe- Qs#!N[+zDsfFL$'Xɴ63Pn 4pqh([}cҾ߃5e7}x&%u:HQi nL;|}~Y`3 j$x$mbϴh =dJ*}@%ִmkgea1I?I=A0Ҵੴ"YaXBeECWI0@H.ҴWbb[h1* W7kꅵ՗L/ S>"*/S)]%I" F.#"C 8LX lA 6ִq'm0ʹwpV*Wചg_7EG!ѴBw̴!ӴCд0֔ Y⵴z،崺#& 鴖xôW޴ 7365Ѐ2R4]F3N" R3'3iKN,-T4vIB4@9I4&43.4W\4O4[44̑4 4X4v4f4.2of4l44QY4ʂ4W54h5U5ޠ{494 5G49545׌4To4A_F434N4, V44}5_-5a4um4D4?f4b4a4m44K444l0$5@45F~!5 5FH44}42I5R{41}5V5f<5(X5úA5?5Z4D55X5"5*(58*5U4m35~.5N585B5(5T5as5J5*15Ve585yi5^?5\5\555PU51Y<5]x5nd5ti55W5f5N3M55M 5V 5Pe5855p@5Dj5 4 5>5v54B5?535r5#S5I4 5b5S4y{44,5544չ15n5 :54!5u&5V5Z\55"4E 5j5 4k5|5j>55li5=5K$5O5175b,43<54o5L51l4'5Qy4ZH53@44rS3L4G5}465'5=I554&4ZX 5(A4u)4C4l1]5)X4/4ɫF54>S4L552vF54{24|544\¶444Q5>545k?5#5@5w5+55N5I 5X55M5 U5 5^Z5l)5iQ5#54k5P5R(I5(v5gR595W5X51l5ڤ55ev5 5w55n5!c_5ĉ5htd55V5h559d5ǎ5 h5j5*A5t5F5U5 `V5 5Es5G4*b5Ԯ55{p5Oyj5 Di5u5Ž5U5fo5`#5ks5z5Y5X5[@5\55) 5W5m8A5 75F5K.5T75ZSk5Ј5Lpn58{.5}53#ѳ]p3ԝ4n4_B144zl244f4a29493w3W/ t4('4v4a4o?3u444qӡ4¯44437=Q3Z4{]3Q4XS")V=cq4R 3 4Lf 64m3e44_3^3ʽ3+esճĴҶ4 33q4>4b54o<4+4{4`Dƙ421?3]*^1%:33=pq2`4!D4e 4)Q44m}c140-9i ꢴд3ֳJU^bOVuo$O^7hObX{<'Y]L@A*&VǴzs|s'}$,U O1ŴCn?/IiA,ӄa4C<ɴ}IYlpE<-ҔvNHƦ H*B %Whkߵ9~2'f_4cP45\!~AٹP`۳$h쁨 6')!V%:y{3 b-2'4δnfT2^4%2頴 w3Mn*'4=1f3ׅEL0@ς3´A M]""Ĵ봆`?2Ѵlߴ|22`VOosN2_xLDx4gD324l 4!=47񕨳GC@ дO5yCі3La˅l J̴*괴Z;!/z]^b[d\62% 3]w)38xtγ!P:C&4DfM'YC̬p9ۧ´V U3U # ijdڴ!>24%jG1ҋQ7Z!w3%3I2j3kM1i} 32X4JQ4XwwA]WG\Pە3]x4J3^-Q4Usr.Ռ4yQBM2@ 3aq7T4]v44W4 ݍ44'r40E`4,43#H43c3?M4*5e4|5v0555 5P5JD5y4e4EE5%4_@5R@5Eh3ٳ4b4Q/5l 5C&*544c4}4T K5Mn3L5i5P5?95c5v 5z#5y54$>5b4555 k4]R4 "?5F4M~m5%5T%K5.Y5ӓG5L53PPe5H-54[a545@V5'ӊ5G5W5+C5k554|)5͗ 5#A5)4b 5IOB5a5+م55Ŋ5R5i#55t5&F55*55b25;um5gb59{5[5]S5155ӰJ5%>5%h5(5.5nw5@5DA5|555<55m5d5J55r5C5U5ni5}5Ru5N5О55۝5.5̏y5i 5 ]54)5%/5N3D5 5]A5k551C5߼555KM55 59T5505F5P595 55?5Yc5,5l5555b5c 5Pu5ǚ55E55΂5T5/E555=zt5ՙ5o5w5%)5ޏk55V4u55qP5:555f5`5^5R5̓5 Ń5t5#m555;'5c35{555eW5bo5sEP5ټT5s5O|5:55-`5d558{5vr5lj5/ 5o˄51:5=51{5ކ5鉈5n55%5Cw5z55%€5K50P5#5Ze5B5Æ_575ғ5-5 5Y559$575 +5[Y5\15J55fd5aZ55658"555Xhh5D54_5T5L.5y5ɿ4s 55p5@44ȽL4\(4l4>N4S4\434@443p44244l`4\4CZ44J/2Κ4{3•fZ4aNiė43h4=4U 4M=44431E46y4j44N3^$44F!B#Y44<2b:4K4W4"=3&4Vn4R4( x諲Gj34D4ū4Xt]3S4=C4-3˧2E^ˇ3644aLE>os4LuR43ך!03qlL3B*B-&4103]f]3 7Hv'4yNrm;2*4v FTJgO'lö2]UpPu= 4.?у\Z'4E)gL4f1/ky (sbǕ`D22q,%̳R0 >U3a<gNYe᜴N=k_;$+( %ߴd촷N8Ĵ 筴S.Km1|%#rChc3|2Nżܱ5tn.S%= bl ~Ҵ4l/3$2 ۳p?'He24eJ44 a#23} #S40~3|M8 3  4 2>d32Д 4y304[# DW4ؒ4p354O*31 3´d3-H3)Ƕ*4p4/4j44O +4 a4|4t,5Ù/4C4tk3# l354 4495ۼ45# 5.94f54@q5 4 B54)?5#55ɺ5_85 -5 75*j5 4p5 565 56?5'(5͕5q%5 5Ka5f5/x55͑+5NE5Υ5Wuz5G5L5D5۪5D55!O5r05 ^=57;5VT5h5i4H,d5!hY5N5u0N5h52f55+b5ں 5 .5552,5 P25jt5D5!5iO5%5/5a5TI57 55`PH5A:5yjJ5 rj5h5235g5 [5?5_w45+5W5B"50_5+5R75:5l5hg5,5[5:D#5 (5 5A5V 5)G5q5-5`545'554u5b_5µh55ؚL5n 55k5Ȏ55M5r5~5o(55'5/=5=H5ƪt5g[5 x55=Xw5]T5ts55}n565x5:55yX5W5 5~A5155p5PSO5]5l53j5M5㑊55Y~5V5Nw5G5v_5tp55Pl5C557a55k5A5kkh55:-5&7m5$T5e5t5:58N5IY55v5cXs555A5%5}5ӽY5-505ߞ5ZL5Y5t5T5!x5#'5S5Vt5$6G5r`5Cة5il5c55A5(J5#}5ym5Ĉ5 5>55饆5h5/5,n5oj5oP5Ү5dm559u55(D5`5`5ĸg5KW54G5˘5 5I5[55ʀ5)54p5-f5wl5jl5=5z75_ 5rw<5u5c5yW5(575y5 D\5=pR5q4?5&m55{Nn5Oq5qt45I55p 5 5Cm055[A44H5.45*C525! 15g5AhD5`c5ډ|5DJ54w!5-585535<55456l4K4t5rLG55n5I]5>05,544140h5?5s'5_R85<'55V4o5Ř5Y85s}55g455;&5L 5G5<4RH4S54yZ54954N5^5_5y=5ڽ4!45L54?54A4Q54f4#44>.13j4F3U449i465W4ض4c.4 4u4uԓ4CGQ4a4;T%5:3R4Z4H33(o3#4з4H5h44Z4'5s]1440N4434熳 ȫ42#4 4TcѴW<4>e"Y 3iڳ5S33~+4_YlB43Q^֛޳@f24[>ה4)r34b4 4U3d/3!ٯ/4t>g34>i4n3~4p4W4̑4 Y4f@44et4;B4q 4/ xd4ƴ>1@4Xp 4C<ϳ4k7䳏/?HijL:ݷbo}"\Vy p4gK4 {+4y444C˳K@q2#Գ ǵ2q` 3*a3r 3ݬS3.f 36L5]4*3ٙ94XPChW,г3eNJmEOP^$*?ܝ3p/k|աxƳĴ%j_Kd3J4K?["pγo;mf4Bn*9Zq޳;N26^h]txѲ]zsuy (;Zf"ȳ3%4ݴM ZG|E4mzŴJsDþ$G4 J34@4{4J4}3f3V:4yZt34*4xv3d Wm~^%c͑$ё ; Ogk2س9䰳礴r{Դ͝%U'/AW {10ܝ&Cy34ʹIZk1ȠtiՠI~dtd4U>ڳ 3qȘ3!mv3^ݴ.wJ)lE5;$.WK6LlZ-3ȴYzi[2MҴȫ-湳zh̴('ܴJ6g7 洀2AIZ9߳'e[:9pO³O:4t͙Pٳҳ\23H4UNK3яrn3L|(33^\VT.rS41ʹoܨ4'703ms4=4'K3+}4(471X3"`4К33@oSb3~203_Q$3·2ܿ *̴acҴiuҴԘT觴Tg#$0x3EB#|̲3"X3,u 糖1*4T744e˨3F4wR441;03o{45 464Y62gΘ&2e3:3Jb4404֤44V23 oC45)3O5BQ34M)4['4 #3494r Q z𓗴3>r74]3Qó02z1hw`& 蕴Q'd3s31U{[$<:K4ڳng1Y햳d9 P!4Aݳ3#54L3|:430k(uww3m4ҴѨ4 [3V2*pΘ.+N8#1nƇ10dNl3O4р4Ӭ3J10/L3o4 234l^f73랎O-3\O_/3 O845]T 4l~h4w33F48~ձ4%M3'J4q4(4:,'4<=5Di5c44y4 4D4)4C7*4443l$5c3p"3Y4A3|j4/ 4<5Z44A5m!t4U4Wz4x4/4.445 3S4y432r.24Lw4lq4ocH44Yk4Ě~4A4#]324XS!C4H@=x`70ϳg22/mD54$331kA^2Uɖ-Kk3k4 Lj32),n3(Y h4"_2-4Iz1Ԅ͖IqGA=m3:.ų]%Qo3vxQeE5q 3vDh4\4!)˥f3N4LaR4`ﴴ%4̈~3B4e 4~4%(2ȁ4?4d64444u4J4{ 544p&5a5&$5L4k59O5=O5q4h4 5x54jF5l5YL5TK5pM5"4C(5?5e44E:5C4$o4444es5ʯ4 5ˉ95S(5uN5~4 4s5Ⱥ4pl4U505)5D54}4545'H#5425y\5+,5SA4yDa5ҐS5[O5D\5%45@4f5pi5|x4R584$N5r5l#5!X5xb5H555 5I95'3/5O54 595[FG5255O4.5. 5>4ݛ4D >3zd4gb4\4 3H5]'4.44u54q464pLxS4ړw4p۲D4r4/2/OU;/s9Hp(d2RY "=2C~ݠcQbm4Zg3|4b &w,4@4 pMJ3+9x\38R23,V2K4/4%m35E_4ѻX44x p4 4h&Ϭ42L;4Tݴˠ4G3I44'e4#4P2Tw4F4h X+SUд ó糪\\~3W2:̴H44] i+4*^ ôo ۴  4%84ǿ5@3ٵF4Nݳ Č߻ೖ}(Ƴz3"z4l`QQXy:i΋0G48Fس)If?^3ߓlo3 p4244W43ء4>q44X4y4mm4(4ɖ3(s8 2H9$jhq3/ 4<3~4~i4l4{494{3O3h39^Bn8 4ҴO3<47Ue kX4M4ڈ#40:{}3 >L4-߳.GL0G94,Wj<+ȭc4h.4Pɴ^?/3˧մlU^ɴ U43EoQɴ/ѳ&LѴӄҴ z>y,eB*/&nL_\+.ɴ.~^lôW9C<-UQes>:5'WҴjM#=WIY.2KE  >Q0]0Q´:΃TO#NXQ8nL@ YԒ!iˢє"$>]6D޴(8vD9i;(vU rRe!)xH *⴪GA0&/B~rT(4_v T*H&XgX]?'l)#U ,29r.qGw?^?C|{|Ӵ%K97{d@)2>u+ źd%(͞=R!N .h"0C7qѶJ_]%"/PUf; , 5V(J6;f///3$b;(rlT$e]ureAZR}}gdCOGex^BggU F6R R"9k(VN`;g_U>l&:LI+޴; 񘈴Oe^ !?g]y 9ô ;|mXJZuzOŲAfiB_3 Yi%Ʋ"?pi 3\Fa;d"{ɴ$3"8VXg4$b4t:3Y %2J23n䴐ZoճeTA/3E̴p@^A4V $ qӴ8jGFfUFџK 3%;244 |4Ug]iW4ͰB2 ~E:2A'4,gJ,4 NURJ{j|4jl424&$4q2x4O%4^9|) 4f\?崅>Mo3Jo:~4I4ֲc-04w4E찯3=ôϴ*3nG2aTc3#N3*y4C4_u; ,3(˲e' Uc\4 >4u"y*4[chʹZU"e@3'HD`3A4鑳+J4z YS7UR44|4O o1' 3l4pIQW􈈱2(42갳O4!PV41!aiS<^ :NK4 3X4 A<:8ǁ3@DJ`tr~Ɲ~ FPHzF[߈3dŝFD@2ثae#ٍRu\dS봽zD4Ayj볃(δ-Cm#/ccǴēA3FK(&4j3fִI|/31͈3I螳0-3JnxUU3W4娳ҳel4>42"-i4aгUQ344S4FM2+4j4Z4V43S3\'4NE۱24a$ɬ3+4l3Μ34z4!4@!C4!44ܷ444r444:5G4R p4-C4z4k4T43*5+484M443n 5J4Я4k494V(3O5. 4g4224D4\]e3 K4B.4.3Ǔ4Ri4lf-+4G4mv33\3z41nV3¬0l!񳻒2֔W5!2:6N3YNv84wԲK3B414nk4k4 45S34I4[c415KtJ4q3)4eڧ3~Eon4{42c[o4#ʳ{39,4`w2@3-4=4焀NUZd14ܗ3_ia3Atc(3Sl436,O4ƬJF\{0z_3P8{Ś3*w3yMB)Elƴ+z\ʴ㕴тj״#7ش&dzX ī97v]E.osQ++hɴᲴh)?0 - QɯMIԴ+>U+hҴ1n roKr״C||2UiC0BK:Zx)HMSpxwwv?A^U5{ːAr7 ;,zU݂Hp `0ɵYA:6'ʵ̔~Ȥä>YŐ4zx؍BƵ?u~źr?_iƱπe}r*㙵tȍ=yѵ G;D̴!]Pzg^5Lf }[Q\cksڿ|Ŵߨ:-ȵ-Ƒ9/іCr=8ȵ$ұV4U㤵pl̵{QjIo<4^=:~*7ݵUӵf嵻qѵөԵyֵi\ѵaoG׵*aԵȵPݵ2{sҵջǵG>72 =rյOȎBҵ*OD~ʵUU˵-9Aе]'U6˗LQ!µ16ѵ1AAµeԅʵеɵĵʋ1i Ϧ3ε`@ӵ *0tW䵒ʵºsDaD͵o =;ֵӵ#eP1KqVK\BԵuDߵO3ӵ]ε6ݵDNs+˵(F#̵NL,NvX3E0Wƅ妦gb$*$K&jUӎ`ydz[M:%brS ?.=ჵ46G,=a$!OW8>T=0ش~1%QQGtq?J,>\W p\ e8J?Clϴ"ogb€.˴ɅlFk'>D"شŴXO-kFϴ0;DtpUuL!*3ִ )ka.jL:*O5[wC#8X+|9wv*=F ;҄{[9#B|L6,n?|`%C5q `.\wS*p}O] O@S,CW:_YŴL7*wF%'ômOmմuR3"ͳit.z3 !=O'䴆NĴi/M :.Xд(7jɟв(MQmɲ~;u #Y V~rմ  Ь 0״w紤aџ8-޴)WpߞOH.fϧ&P]4 4G9`6R4 h_2svdg2O3恳ܽ2%J4}4^30r.3mt4`4p4ܲ3!&4?4 ~24+e4M3S45F4Ca35;4F 4߷45' 54̵4W4!4Bj4'&5ٔ&5$4@5:*5S45Vj4 56M,56IY5X 5I5H455F5<4QJ504 5kQ4t5[750^5E5I?5PdT5< 5cD5)5H85tG5/@544P4yG5544/(5(5>95 5`5C5;4.e5Z4<5}.5׶5A@4 5u94J4v5y"55-5d4 5+4j4QG3 54p4eT4(T44L4;V41F344~35T3TD5An3[34 5(O4X5b55Y4V4v}4&P4'4k40i=5^7+5||4 58A{35ߵC5&4-4x4 u4.4|H4z@44 5V 5:+5'4W54\$4f?4{4D4464K˴'4y644ԍ4v4y4y 5ۗ455v45D4 44jx4su>454I48~.N44w444{tM4M4 545e^4_x4 @3x4j4`.4(4Y׳=3'i4U4`M15-3:34-475')44g5-~A4¼44 33,4}z4d44]5ܢo4y3#55W4U}5Ţ4 4f\4Q 5{}G5;54p5AD4<}44i4455V4$456 5:l4zN4|44ʺ4X5)@4s5̭4&4 5 55U4X505 54M4V44ҟ44J444?[434y4yg4Ԅ4`4堂4Q4aM$4aD44Z3g4u4\55/ؼ3R43J3K44.M4ts3T3b4391(34@4i^454wf320L439gu4 =4'L$4345FZ1ڢ3?|4蓖4{503%}3֊O]k4a4#844K4a4MW3N3m2zk3pϰ4(d3(O4贎4=344}3Ҍ3W4yJʳ9l4 { 3G2΄3HR4ڃ64r4}3 4&4y3\U3zճ8f4s3,4o`4J`a4N!^2B >5 74=1OA3OT^4NM2ɵ44WW^3]3d3DS3ܦQ44iM4}14Pk4x45EoV!4#K4f4(4 4nw4O423TXz3vJ QLܞ³eγXn133Nj3ͱOb4iVa3yk𩟴чմ2V:4uڴt^a\-l2>3Ì4Y=3MmzRٴ<ﴷ"g+mLܴP,hnhǴQ\>.-y´Wך3DKb&RIM6ߴ=刴Jٰ!xW$O[<\7Zr3tJ2ӣE4׵PMep)d2 DZt ƴOā *5ִ@}4i˴`ڳ' N1WBFFQ2t (&WʹQy 2P(Ha ?ƴqZJwyv 7<7OŴŴX갇3?H]_8`дV&<c8Nl:'.Aga3 }kkI]"7>0eJ."m=!yЗ/ ´8 ^axm8V ^HP3B.-1"uȝ(:þS״o|2DT./E.Գ&=3?c2b04v3д4ʹU:U96 ܉|紶kW\43óTuRQMx3}9-Ӵf16o{\:Q>г3;vʳibӴ⦴7_Er ִX%Yyӂrp}+{6}㴷n;ML JٴQ"N4ܴb䯴u&%E啴g/9N2В;2o[Qƴ-Nٳ vzں@%4%>*Դk4B!Ek(ܘXz*Bg?;w G۴jA7~zڴԴ,!6b3-R GAd+SwSGRZĶي@; 񝰴px}M9޴i2ܼ4UbtlK|d\4≯s2%b12Pi3=ó3g3s$Y@Tc̍4@̲S4ɅU=4 64]1 3?4";4Mc354Arӳ1~א4a;4S4$Zy 5783Bo44! 5^45 543d3N~4J4&5?k4 43#Z45B554A4>4Y54ʆ4R,54x154BR485q654 5d5M5 5-5T54Y5S5*5<5ۗr5sn58(53X55`j5 5]-55Y3S5D5h5P5tn]5w5W5@555n55_0P5NN5)5``5Ȣw5q5 5"U5Q|o5_5%6W5q5n5Kj5f5[51|55s<5ɂ5$i552Ɍ54ڃ5j5q5`5;5ᱍ5%5r5vbe5R5G%i5,5Z5}5p5CY5i5ل5@5Bd558_5c5!y5x5y5S5aH5 H5X|55{5N5,555h׏5CP5n5L_55'5"5_5L5L_5|ʰ5t59,5۪5ڣ5(J55I5웬5o[5Y5%5KJ555QT5\{5L5ݡ5A55@ƭ5>5555&5555[55K5I595^65Ls5 5"5 53?5)Z65g_5w555n5 5cH5`h5>55K5jE55 5-555Ȣ55U555J5/O5?<5Kb5 5T5R5" 55}̏565B552&5e55u5Z5U5V|5R5uB51W5LT5mX5<5<]5r45O5\ F5 d$55@54CsE5`5؁5FQ5aV5t5/4 T5,5`M[5545F4a4e5BX4LH5E5n+5O'5wF51J}5b54Zb5.155G55*qb5QO565_v4. 5v5&*G5Dyk55d45'51'E5&/5$z5)5tz35c5T955P5|]5d4`4$4\65ك5 55+4|4d5!5#5(54"F5y 5pȠ44t55O4T55ի454f%54f4H4;5ך4*44<4355zl4j4:8544J 5425552'5B 5PsH5}r54M4 5 %54gm5^%5DL5ι4G5Б4ZR,5 U44^45Y<53&4UM44/4$L44w2!4(4F3y43[44(4)4 44s 2#44A 35_3}4٦4l4t9s)e^F4ʱ}z4NJ4C`4pdH_]13X3\MLڜ3;ڴ4F4whN3r36,3ءjWB$0غ3:\[a4>%4EU׳ti3ճ Zg}yմϕ_ʴQŴ)Ҵ4V!ݴ.􉴒t' Ӵ%ʹg-hJ⴮=jȴwŴXh /ŒմqfR˺дK qKk+* dzՀ +쳛GyȁOzճZc;xdPꗱrŠ= Htƪj⋵H],vr`x:p\iEZZcqw58Z:KttTpD 6+-+ȴA =D4 e;x#@=RMu}/(E 0^"9.Ռ 5_J-K\XzZ#$,*C䴚s \ ~jze>ݧ +1|I^@#.Nㅵ!/ L!njH!d8#+,T$1fM>l.qV紣HHM64ɟV״ _ɴf3λF&ake&&9״lq01ࣹ@3d|y+& HL3!H$r(z*]4Y3 %&fm*4444H3WK;yyP~p34$`SB]'݋YO9J.δY7 urFͳ&T]FJK4zp2|2Z"z]hPW*/j T4Ȣ;T޳nN43F3 ʴ~463AƳŠ4Fl3!~H4Q443x3$4P8DO3q324I4{ 4p425|t5%549,4r4545-3g4q4gE4044nt5>=525h4ȥ5ck75X!5v5 54Y5|4\25d5$4#g55 i5FN5:U58w?5Jh5 5)243ԛ545M4e45 5\5E{,5m?G5_J5:>d5`l5|5hg5;5`555>@5u5=4c585 [c5"JF5I5X~5uT55^57w5n_5!5D{55腛5-Ȍ5r5 ]5^5=5T553!p5Vh5s55~65D555R5~N5Bl55h5/5X55S}55{>55959-55Wכ5n5^5kv5(g5TL&5?55c5;g5 v5*Ϡ5Φ55|5"5Jk55㘈5e5 5M5a5ݣ55&n55£5^`5d555˃5S%D5h55dv5,5[F4VO5c5g565N5 5P544(1JޯX)ș4h4G M3TuGa|q1?[:=jy3ٳ՘ooo̴4Ҿ*㴞tҞ |;/} G\,xꥴNfδϴ4.ϴ\̵}[(*&38A]VnF򼳬ش-Cֳ''ò"ʴXCyī.rPLWhXϴקZSv}. ^ 3 ^ƴǦm4NJ2j0Cܗ+jw304[ѲM4F^3!4Mx32= 4kA43;\v3ΔA&DS2ٚ3` ijW3483f4,444ܫ(yk۱f0474N.4F i4Qt4P3*ܵ15o4j194U4oۢ4&O*47P3\d)=4!;4;c3,G 4J#4T1?3 ]44s3 "3ɟ4.3jX34G3Q4lU4He|8(w4u 4߁94 43mk64<74L xzn4B3Q4󂯳_93"3 43Գͳ.2HV47#f34_մ 4$.ر$>Xa43|f3YH4 sm/ڭI3*r:244t"/E4Y4{r|)\^9i3t˲CZ7~sivP 3%۴2:1be;ܷ3xC+e%EĻhXkџ,sSʴZ1A3ӳ>,3ȳD4&h5/t˒ó*1A5Vd@ݘ3:s޴OOj4!> ݇I>G2ᜳ"JB1o-ԳU%Miȉഛ紱3z n@(s^"TkU4^_J8ڴjc1Z3ϴi?]O32q4C43OA424?V3h;D2.4D3Pr4j%3EI4VP4JIA\4 3$4p r4 ^+ 5R>4` 5]48D4__B2-i334J4hp4)4Q*4J4J=4у4˱& 5un4[Xu4}4HR2ϕ'5k4ˆ4ޖ2MX4ㅯ29 t43`y243u!3qp4a4gA 46sV3%1jmn42ᘴ3-PΚx {>|4Գ*l3B׳b4;3q&UWŎ2}n4?I434⺳k3924Q4o4}!G4fK4kR4s8464<4{4{3]$4@3474.94R444QRd4n4m34[<54)3On3ճd*4Lk44'4<4IV48x5+4K4`55RG4rGu4'44x35Q 5u44 468an4v44e3+Nސ3o4δ04TKW4j34 V3͍b4+52%4G53w4V4"$5K4o0J,54{ 5494X75-5+5T+4w5445/r5;5Ѱ4l$5^=544y5{%,5O4]>57459?45æ4Ӳ;5#5E4-z5G4 54p)54j 5,_s495/5Fo41!5k4|@5}Y"54T44 4I4k3vq4454]4Z4X4B43Gh5 4jh44+X443(A4P95r5A?4R4[4$"4 65w 3+e4 h4B4p$?4ר2)4&W44:L4Y4+33ǯ34`33 4x4p 3 _{H4Oc4OƉ3k"3/Y4|4"+2`C 1W)c%3u03sˣ2p#^S ^RT'lk33Q"մ}2Ѵ_>4ô?״-3ǴѶij7)S~ 4ʑt0䳡]:_ %4Mdy:R+V3.T%0iST U UbB.*!lƴ; _v!ߴw8^ܳȟ~Ѵ` ^a.jG: s EdUg7$erS*紛,wEQٴڴ}hsV~h))t YX-/EǾ3Aְ>u.,^ݳ8 Ux3Rn2Me,') V H;/6oծa OyJδ0rzfϴ 6ϳE΍m"˴u.UU򴧶u #(2UHY'E$eB-z %^*'tPc獊-y;@$C@`|nr+ey|=kHۣɵ+khhr.%G-E֍ڀڸ !ݖ܍|W`'8=C[RnJ>ףF^x_ȳ# ojHʼn6N]+pqATYD*[eR/q_撵qV4+iIG@W"ŞAbQ~8w7ޗ*1(]Sz*< 8t x}/% ^]+IC h^LJ*t_Yyw= iA@R55V tnd'mZeCׁOt;R43&ձ v?`$c:NuNj.le(K]\9T(Fz95=0"ǂ4CI%74Iʹv ܴ+A9Iim¦:" Ĵ/KW)Գ̴meGVŴ ߃"Ǒͥ"?ᳵf2M3߅X$Q-ٴH $9SشP25!aQxvٴ7Zdz]*b' pnyJ"v)e yT#-u#W"8j^@+[ߴK63Eqcv^ -Q~"/y'òvm4}3 Xn 򳚕ʹm#@`q +&^4Wo˳hϋ3lէ3:$푛a#Pϳ0!wi}d9MbDzs=iB{'144)0@]R4q;~4a?4239#3M}X24r3#l4q494=375A4"44)ʼn4޳ rB3̘4Α4H44 44< 5e4??:4i4`.4=c4p4}492W3CdP7U33h,404>V4dM4I5)39~44:44.)4_2D4鬚3Z4}4+4ES44g4L45 44qru344ۚ 4B3y4D44z4x4q4"e44 H4x؜4۹5Ó4گ.5-ǝ4I4P4J.4Hf&5T4 483/w544uu54n4_44i4ѓ3xa4s4Jcc4˟3H@3{40tCvw04jOc3w43*|V\4dk,H3]'e%ѳ{4.<3!Lcش |4E \4쇴̳d4-Т4d? 4=3 vs33ִ22ɱ i‘4-4;3 4w^cдO^m-H4׻eTr4ı⇴KɎ2,Av4*3ڱF2ƿ46\/-qޘ3޳{V4)V%4khN3񸧳4dL#겏E394| 4R64Fݿ44sF44s4 5f3˳2r+Wdu44G4fa3s4!k'18&4$G~3A4U4S24@82*~2@q4?444iN4u4P4af4 644+]k43޲4U3 5XfLl4o4cv4|2@b4񅴙D24`3jTwҳ񲎱V3 ǴLγ^49` 3g2gHNN4aD0[4}'\3Ό![?ƒ5)!J_w4kң^3ѴDJwɶv[<#c7<Ĵs3\I5.ںX1vy0Htⴙ:0ĭd;M\`o8]Ԁ46/NΤd?SHw 3 5i4n/4-Y3o3N#Jt 䳴S4'wA8:39Sx.,rnxm\3Nwͦl xulj5s/t7 ڴѠ2๬XE)x. ɴ;ǀ^OW|Ǔ'޴`>WN+ഓp[9?h>ӯ1黴ʹ%jIRd.6N'A%[شwF8IGδ7z=dʊ:򲴰ڴnc+Z2y< p@ElQ+#m[͎Ҵ VeP\*Fuڙ{AQ4!4(EVmг.QF :怹]WD}9ߴ,Ia7!M'4״RE Դo~8&۴•++'o3֦ `2@~3F3DKt.ٴg 3dm@]ًZ"Ri4s촙ُѴ;ڴPhBAv޴$/1r&M"-7Q.W31sW9jB F,/Ҵi"'H“2[,&Ǵ;c6]2U+z/^NKv@:z@Sgh*IiU@>Ir_B>g-X?T%66fH^CU.?Y?=&R{`-әz{s/ \tac$=wJcpٛ#k؃,)f ?YGȴ,Dh峑$qyɄ$淴 /|!)A贜=崤}UczZUXwR:oȴ(+d״OʹZB4H:Դ=I?%"붾n\iz\[vW-'׭ ?&Ѵ2Q¦7aTôm񴣬i³{ʃ䴸8~֊'`t7״J B4}s´?.2[6g3O>7Ȼ/41R)444hك4Ġ| 43>=4MS3y 5 h%4*5H4244,L:HYNBg3T 3n(*{4F 13^3< 4`ڳՕ4&R )mt4Y4ڲ0p%74瑂444_uP3D4hm4y32k 4h4#V4L '}4o3稌43jw4v&-4/o?*3e4Ʌ3h4<*ӳQ3w>$2\2C3n%e #紱9^3Z5q<2(3^`cu³(45:X42s|v)(唲RNX|PbKҾ[nge)aۙ!4~3v Vo[\939`3ִsVpMw_E S43[v7A2oD=6R'N%2:msOQ3$4^봉)V3q32ʹg 4!)Yֳ߳Kmp23hbߥ3GU?'\SL&M?~+44">a^(4hԴ!Wd*2&gk! 4f4`4a4O4Iٳ"44v\W^4QZ2מ3x4 2x. 4'm%2Oܱv$Ae2ۚB 3m?("2HʹJh3򽦴`4 d3{)2[*'zbWҬC1iBjƴY[?-δtE? aYp~~>\wK{nJԴx^a(Ų33K#ٗ}"[AM33ɲq4u,妳f6u$h%3^Yޖ3d3"14/*AA2ڳ(\|4dlLj۳`ݳ gr2Y4n5ȎaÝ3?s \qSGl34ޫ3(寴N!sϐ4L3tgduZ})l4 0 ۡ4:1Qc3HT3LmE2M Z۳ꬲ3W24I4133a4036s3Bf474<^3Ά 3.vk3q3a˰?4I!4U4h4WY4E4Ԏ4 F4;Mt)2 7s:s 3.. T44}|>*z'@Ջ$3* uepR464(63l&4EH4زô@H %R쳚2Y_3 3o %@4b3(e4Zt4N@2 vٳi52b4223,Ym3~$s.4*T3{~X4mjF>Fc~4mH24BVùJ4< LDB4J43z;)435je2#4[ 4޳.S<4T? 4J3zu7434(4 tn Z4ݡ4 742N3g4j&wƼ4F4x"3#43qg3B4E243 4%4++ 4"S4ޟ3˿-4{454!V4om~4 4 5s4n4 4-445 "4a#4444^4 4\45fx%/5gS4444K 44"_52::4/4e#5)5E5:54 5w 5fB5gA5q 5A4=5 e5/5S5R:84P)54L4/5 f4q4V 5I5vR5P)4 N4z.444%5ǭ4-k4K44 5Z4?;5KP5$5 '"5$5 -*4p45W4464|WS5a 54~45u4455(404D4-4*42 5夽4 4{44^k;5q415Q5R5245-$5?543\443434c4-;4-5g4V5w4Q2R4n4Eh4H5Qf5Ђ5H554|7f544j5C>5|5`o5:5pK4"!5N5:5~4_k4G4c65ˀ57E5Jq5>4v&4.5c43r4z4Y4=4q48|5߳3H445ɩ64 4e4AZ54y44H^)3}Bf4^37$4R! 53C4[3U4KW3*$4ԗ34;30 54=85 ü4oniCa4b4z4c34ܠ4~^4mؘ3Q0<4k2p4=43FbV4N3mL4(3PR404YEJ4 pt H3~Dg!/~ 3PB43A444_2P2{V31rs1q2T48´RWS昴e4$4ywnMHj'<(~[깴 x4ggCPC4ۑu34RqC-3͐u:\մ604{}*vM3c3>0v4s3b3$444k4 ³,k<2eMK 2kݴ4mFߴ,Φ2~ﳶT2δd?`3ݠX n8y3B-f!ųs4ļt3#cs0ɳٴ{J㴜 yfTôix98δ/۴AɶG~E䛵#tJ>K3>[ނ>Q;pI#bI.Y8gXMΥ|ffA@`̢a<"Q}hTCE억MyMr?%w:ƵƖt+w Ub䊚z`\oypc{/z+Ez'*VK&#\ִaGll$rvG(nfA"Éc$ڴ7_Мe-QfN/HcFnCUPzŴcV!0%X_krI-0BϽ[PfWHG$v).՟㣸ߴ/ Js1v.*134!9 !L|͏PD賁Em`23(3LWҴ#۳K(ѴVƘzwheZ4fu/M `q4334縲nⅳً6S4HB`q>%z# /`4gqtڳv223kib64003mS)3C%Fz.G2w 43Deo}"CV4W4&4S3 i>42ѳqp4 ;4nز"%4/:\4"*4 3)W44BR44v4Y4P3M44 ̳Bq3}594s-4q)3E4|x3F29/˳l4h4)Q4ye44N5 04K 5tZ4e!4n 4;\35 3='547l45-}!5U4f\4f44o5F5x4/4y5K4%4ͪ4h04 4&4f55e#5_4+4y43?4h51}#5j+5"k4LH5z95,75W5ʡ=5$z5 V5h5O95g55)5>1|5ԍ565i|5 45`5W5U5l5۽p5Ik5-r5X5P5bM555d5ƀ4]|55מg5tj53>5ai5L35?41u5OI54tfY5e65Lv5&5 W5ɮ5.b54_44<5t4I5j435Eq4,5 4 5]4PYu5544m4/&5Fu44{4nr452494Oo5+/F4,4ᇮ394vV4a5ڥ*4 c5Cv5x| 4n)4Y4L43o?&5v424F4f4[5me34Tӳ4Ǘ443|4r3:3K4dK55 243U4"Gr4HA434t34v)S4]4*g4!nj4mʴ2k8۳4Q$4v 3h$`41bѴj4|35Ƽ+4n=4RxxүY#34+ 5U`444N4 4( &24Ee4w4-4o#4>T3J44b4ɽ4l53(5$3539~V?4\4sd4&4@?5c40,5`!5D4640z[5G4fX5+54Al5X43U254q;4 5]4844Gk5P?445N5{J5J 4 4[54:45+4;5}5`}55)Hc5U5ͦX5ox5k5=E5cZF5-545iX5J+5Z`5}45o5R5yu5:5iy5Ҍ545CP5:(g5R_5w57J5-5B5G85r5-H5>45 P:5B?5zc5LE5_5ow5^l5K5`5X95A5{b5!25J5)5y5NX5O55W5i}5r5I5 x5 5%r-5OQ5Ka5w54|e5.;5sg5^o5M5/ 5,5RH`5'5sX5U51C55g;$5`5>0555~Q55 4m5555k"55X54-54k<#544oń5̳44759!5 t434<#494m4:4!4&Kj45P4u.4[’4ӣ4Z5N8N'4\Xó2'?443U3LQ4~4iW42>34 ೋ/4JFZ4C4w Kf4*48atP4?1s$3GP3axk&4fZ1R܉4v4*o53W4P43+ܳ|w424p33_3f"2Ŭ4T|4K4ߚ2 4[4x74wc94Ƴgx4lV42ky3ve4!43$4U4%54$S4ة434L4O4xE4b5D5<"454]15c55w4 4i"5a 4}4+4_4j4JW5444#$4$?44W$4Ox3Z4ӂpC4QK43+C&4444p5D4r3C܇4434Xޖ4?3Gi5I44Gn44s) 5>W3!4=F4@44_l4j44f~4FU4Ƕ1߂484sZ43!<ʳ4Q̝44C,4V\3>4tý4˽74^ϳY'4l!44t334|44ttc44E*%ѳ 52W 4l3‚jmA 3W0F4Yt3"ų!2Y1ſ2s4{?2p/ڴQ鳁34SV3.ݳXwx #k5dRgݴ^=OZL2 71ߴeB3u>a3axx%E+x3tȴ[+Gp3zH~3 ߦ=Re361i y ߴK=3I)ٴa)㴽 G#.'DK3׻be : 3ّ:Rߴ0"ԳŖ2{*ZdzHg4d+4K? 4"4@3ʻɴ4IkkqAP˴vôhuᵴ̕#I<\2䆴WdǴ4%:Ԇv/02ke3_5](Wʹw 63vZ2@庴Z2c-Z򒲥sPUWV}4<O?~-#tY1̅3n!BĂxG⦴h糸"j ƴX*eȴR٨f2j&+y@,LܽL`Zг!cJ;^–`V'%z}R̴IDI V`!8O#u@"<) 18Z"U `' #㔵-=dЂ,شsBHkC;MK@HWOu)tPy-{-´e {scǓDbe KA9AZǸ*= ]F<.ZDeqϊJڴx1x i5ѴL}AM\TE(]b;2^`3?óz@4,\҄ÏwTഗˆ`pDȴ"HU ڴX ⇴i)д״ ѴULA%IV~n1o"rSӴu:gѴy㴆7rm yĴUm!/hoߴ񉏴^mմZ277lҴ/֠']7Tzٴ{`Tx,!𡱴e/ijTf$~K]"F %}8 `M콴G!Q T8Dtb곾+..SpbV#.\#\$vFOK 60 150lb l(\ֳSR%㴍e¾VYSV7/1tq4r-i 3Rʹ<*˜{/괞GO8Pԉ</Ҷ۴M6HԴegY-aNtVӴ"g e´Vgݴ&|<h7#*G/ł+٦BڒEp򴲎q9 P׎md;(˴d# څ7`P)ղش\޴[sZYuO}""2  ?_^\Ӵ;Qp3Gz^ 4 m6lQ;43 &賚w}3-USóIΕ賮 Ɩ33ľ3=`4'3-ŴfHV I0gQ44Y,"1ų04.z41o,31;3m4?4m4g445^L/d24{4ea464R=/43BG4M4j4Q764g\3|-4l37\ 4v5)3G3Vh4_l24'V4Y4Lj3 4"~G42J 3"k̳Z1ųԌ2P4&24Dޤ3zK,2M 3-A0jW3P3F.3ٱ3i4340RI4؇r4f+\3Z3:3 l[3E{ 3;g55E&G5R}5b5l45d5[d5 @5;&35$5S5@VQ5,y^5/[5XfH5\5V-5iI5?V5_5 15G35"5#c5X"5ct5̛5524$@5W4P:)5IR54.5?5]^5`?`55>5j\5:5D5[5;55;>5955a{5>545t5'd5[C5@55>55X5[$5H5P4ʍ25{5Y51)545=?5T5g(5 d5H5Bb[5f?S5?- 5jm5pM5L'5 U5)4B5t5V4+5D5(5e_[5WW5I5l'535r55}54:!5E5@5U45d51444E755\eo5@!55l/(5N^5HS4OL44m;4dk4Vp44 4I~44E4傒4L4k4N43̷4/ѱ{4Yb42/ܳ44nb3WԴvKҲE64)z@4xഔϴ3拟2C=e&GmⳇPI ^o22Ox3Ն3e37ﺲ5x3!P(445s33r4~i3q449O44H~4/u4[541.VK43^47^445{h4?4554x4 5/3+4 g5"24`4U4 2Td4\4/344e4I4A_F4lH4C#AljV3]r ֳ#Ye"4< 84 p}- mX3231EUJyVz;Ӵ:k;&Tyd#o8۴o I3ϥzu$Kr[u)&ٴ (- ^u@h3% ڴ5Ba}3Sˍr 2?f2Ja䛴JOǴ}$ײ8x[hŴ@ ֳ4m+P#cɳNLq܏3`8Z4Wƴnʹ6~,nDZ 737 QaDI2k1>3۠D-3ҮfX>43!224$43n3͊4l 4];4FA4J)AA3A1v'z4h4 434\3H4o'L/4!4-3ZC4L334D@3c34b34&V2+L4j4{4 )44+244Z4œ330R[4(ZQ4|44~4S4C$4P/5X4W3g4F4n4\4n4iw4,bJ4R5#4 3{4"d4XvnM424Je44f1t4 $D4l202y94F3ų3a44q)=13J43o2*5s3E~4=s4@Aun4.4[6sJ4&3kg4# 3Ѥ4a4q54Ґ45È5Mub41<5剚45k5G 5WO5 5[5?5 4+gY5&5Rn5tL5s{5=5=r4 54ٿ4]D54y45[50F=594=5V}M5l5Hfh5 5@n@565 1515%5v;5Qm5#5gu5w 5#/>5Z"5475K5+h5Q5>524 o65U43+5435>44DE5 4CYR5LH4Q4M5Q)55[5u15`5Ґ44J5L5v545>.5xS5щj5ea5L5lp5z*5ƁB5:5 55br5&45^4 54n)5OC54j*5T5SM*5`44o4c5ѐ444ǭ4844[ϔ3yԖ4/A4•45L5[S45X3u4˕4 4lm2 445O+4k3]54=944M43j+4w5q4鐮394|[ղlp3eկg˳ނ4s14$G4va34T3j3Rԙ4a<@33XC zsT?[&; 3KJѰ8ƴ|BഈP,˃{]hp|wԴ.$}WN-ȴ' <0&w.h [j?l93B†bftd jABl^go]fw;kƞ;i-"zoj˥X\63GG2㙟2Fz zpot.ɹ&aiqxkWhd5A|̆lG@P×i ʎgHzxjY>サ$ciSJEV#ʀ.L.``YxՌxR02}g@P^GSi:\oqby*o1_kiDKRUA1'ypq #1; ea&^]?]-Fm>F$@A qfjiYp%NKAgIZV+5ڀtU֙~"Ѵkyno-^Sazs,dm0o7)v%UTr^,ܞ`0`p2h3цc"LcGM^M8ko@^C7%`y":N+WO$n#nCϴFc%H۴xz !FQϴ%3ߴ3*޴zeb(TDeN@5 h1p#kgCO(6t$@;/w$~4EM|?]u1B1_4AchFyt4f#AZ31aϳ2Ȫ׳e54>i(4߮d2|NϭNkN3W3\)| 4? 2;34|^?W*,/7w2/K4&x3qմy(@4[ <#1Ri\C4444вC24dh4_ߢ4lb2S!T7394n444ё)5Me4_34]F34<4,32Á4@O4m 464wr4054r\I4+V44E(44ϻ4<43 M4z44O4Oʃ4 5 4~4c)2E4444^4T64S34Y434Pݲ޽ͳ3\3B&4N4W4k4ȴ4tzm3{ݸ4 pf3.4س>E.G3' 4ӳ+&FmF ^2\~ 5 8433425+4[c82El3NU4q4Ӄ4j4K4$44l5&5555%/ 44(4554s4?\5r4_4q4&o4~54545 5GO05Q$54 5o46554 4 45<5m5]47?4_Y2535 +4ڗ5X154N 5\_5(5gF5`b-5D5c#5JsN5N5[5u5D$4CQ5 O/5N5r5;55rSs59Vt5i_552{z5KT5|5|5a5M5>5?f5Gk53_5_65H5Z5g55ʊ50\55{5&5'o5AL5\}5a5@55F4^5B5h55^55]mR5G4f5祏5xFq5?5 5j$I5Op5 5&5%i5,5>Ư53N5_?5Aw5_>5J?4 s5055/5} 5xK;5[4>G55I535[45(05zQ5E5d55:5ۛ44535cR4v44xj544|5t424s4Z*44#44gO5i~4TE4)4*4aG3z5.44Ӌ3_g3M4&Q4[3e"4wU4,^47kn S 4,4T5S4Ԅ44k\,\3W3f4 4IDzՋ4R?3P42-4z38跳G3՝3y|3- 4w3 4V4 4DM\4@ݰ2(;403J 4_eB44h4ّ4v]4SaK4/4ճ4`_X435Z 4 4ae414r44#4P`41 5 4- 4 44n 4U\4{4544<45k45@4Vo4R443E43>4(54O4"4̋4<5/444&c5|u'5^4X 5;5v455^5`4LF4a4LU514A@4R|4p4e4W+433`244J4%4\2Zڛ44݋Y4T4qP4 n24G4K4hw\̳(I;kX1ҳdz B34XZ8=Y0t1k14C3(3`k9T8ޓy60 7:۴# B<4d =2鋾#δ:gwJT o#3Rwh2FC E0ؾD3*2gX3&882j4YR3ڪ-G3M]3Sɲ> i:3ÎF3wҴ;@3ȋdIخhi3B3#2rˇX%l5F/2KN%36MlZo2b?Ϡe=͛)83{h)oHӓcgkcֲ4"b?7#463h2Ꜵ"4ID3P3wLOD4N x 32jYxO.vJ\ T2f!4\4Aa=4s:@2Ԓ3ϯp4D3#1LTj4r3;4@ 4*3D4~E4؉3)A384e 3b43(m3T22)mc.4p%jղ`UX4y7|4nt2ʳP~4)34 %;43u:l.O4Ѵ4`1ϯ<]4+gIwGP{58fTIKuֳxC 4FG3P%.x2gRג2H()3ʬXTioѴE.&x}җ_ Y:PݴJ^ݻћ2ϑyO ktT'<̴p!jpXA.S4;ddv#7)bsʜAsG γه!b4OS-\򻶴}ӳ | rrhb eRN2Tt4`h3YŒfS QCdѻZa2墴 fh\334O5ִ^C4qw<4DUFQ0fn|Y&9ڸ4i4v4{05ux%4Iô{3Ɉ2 n4ʹ0H:4֦L3@{"?4X3s%@43z4G x{4,4O4'`4mw{2q4h\2?fd4 |3Sk4¸4o7ӕ5DzQ4-344N4DW3A2e3tN4"33n14K3tD4 23{4{4*Lڳ ײG4`T4Ő3{=qc34;{4x3i 4߲#$H(4Ir24K4 4p042 474? 544m48 5>E4n 55J54Ƌ45555-5f5zq^4U4K4455ƶ4G)514 *43o4!4࡜45~48 554E 5:}4p(43Ʌ4_?4B5'5i24_ 4!47J3n4t44[eu4u44t_454;3 G4y44J4:?4ܷ4 Q4u9J4mg2ijM4qL4ˤ4 4\44`234e]4X1^O4L312W42~J4g5444eO3+9䈝3 aQ44 `b3s403y04(4Q4``3"1|49V43{@4M¥\N44C4k!4l|4bݪ~4P4.ܳo"4=[:31~sP4Ϗ3?4a 3Ŝ1k˯5~ghtҴѴ#o 2E«!> 5hZI&OمN\ڳS3=Ɔ3 4ݴFN@{4'=FVR=4)4V()29z kw賖r9C3(24R3vt1&]`44o*-0R2~3^]#{[4V 4sz'4@=R^u"Qȱ QoIBa/2z 4$G[tNhƴlHαظ3@2ɳ3\O3F7! ꔋ4ƛX29ʴFݳF]9@-v#n4327۴UC#tO񦳖!4WSbmlȴi=SvFbWg> 9B+&)˴6"]fTe4*1Ĵ[>?~"ɴډ~ϴӟ㠴}_:G>Èz`E;&ܴ \$Bގ*jtK󴡢ش>U znôG/Y1^">2(ƒs3EZX#4|᷋5▴Dȴ.:P=PB>f4γ0*H鞴$dO"O˴ߚ`2l쾴j?o3x0[uR(ʹ`ɴ웴n %DIȴ"۴06+X7un$Ǵ ތ(ߪ# ƶ Y:L^OSട慴 㖴}9׷^6w+.ڏv*Ͼ 팴> [蔴OL.1"9?q~l>Z9! )Jhî=.VRʴF9ִgj3g'q2B1W~;u^3`]W46K!]t~:QVn_OOR[Ch3 3#ptd o6ٳ8(3c-2W.o@V)i 3?ȴ 쁴AɳVcm3瑴GSE4G/õQG('+-"޽ hpW4hz(/,3'͹䴸139&ô>E`:Uf Sɴȴ7ɴ3մW'4,˅_5洖/6}<3ʂYn $1曵n{A6a(G 0/P(f9#RxCɀkO|\hOs>+&"?۴A#BX*Lf$صS\';LYִh>[ش{ϴm=?TE:9KH1g^:<,BϴHӡ29apN;Ko!h,<(ctgJ95@y3enT?1,P&EY r ?+74w;J: Z5' 0,/3r)( 17+2*" b83&IG]jO$`^)'qDe*BgD'', $?;fʹ=jƴT|Rz6(m㴿-/`z/*sT4[&E^doôP #SĴZ䴱i)Xr?WXEg󯨴6 ɳ s|6gl'|{DI $`ڴO lNi; ]4ִҪɳA( 2"IKqd Cb%Ճ35$b3q2?zvpsH44H4I4 t 4.j4`;4Ι4ɢ5˱43D54;474I 4r34",5*5'5:4+5 .5CL5r'4d4`#5bX4('4J4̓ 5V,5x*5'54I/5V53R 4Ȁ4ol4 55H%I5YL5†5oo5A5!5a\4D4y49#54_!5fg5d&5a5P&5Na&5#n5n5D-(5qX5jg5݃5ZC5Ms56OL5^515Vr5]5C_5v5+pl5!5K&R51J5q5i5.5{ψ5Y*P5?5]5/2b5)_5;ԍ5ax5"f%5i5\5t5jNB5)k_5VHX55jQ5SY5D4aKS5s25bc5mc5b_5Ia5L5H54z5P>v5蟋5&5IPa5yI53p5a5>5F5h458535^q/5Y;\5X#f5P55KG5B 5A5{5G:525G.5=4W5&M5}4~R5!5~4g953S4{h5j5K5L4<P5ij54];4҉"5 53`5\G5В4Մ5%N5M4<5?5Yq5&q5t5+5|553^5}<65 5o75d5<@4`y5dQ5475<5X^5=65Hc5i455H5#5{W4Bq5M5>255%5/4_52/55ʚ65JU5 5d(55;5B5C 5ƀ055@D584tP5߉>5 5V05|545u s555(5;454R34:4L41`s5lI4L255-5y4rN5o 4xs4_5ˌ4+44 4QD4Bc3445f4[H4Q4Ta34x:R4b4F4Da4 F4;s44Pg.M]3$37-46Ǵ:֭m&4+ kLώʴi ȴJ0ٴRo2h 2<\2)rh ϴT&3! 72ӕ  F\:*1+hW/8IδWڴGUS8 )(RvmP%hD SW#Smi3 6& m@G-$gV }^U0mo"|䦳6q-WA8}!!hj!2ko |ﴅʹGھ״"Xr(S659ޒ"YN$~䥴D[ q/<^Iv۴ce;-дGҴgܴ崵 V^0l>(@7 %{| b>4/ʴśN6ݴŴFƴ)Q&t LRB'kE|M > 3QǨ3AGuⅳcEw2_ѴʼnjRURy̴(ִ#pݴ:nꔴ}ixN}54 dLw|KgִB˴g6`JSw ḴvxĴlന-bPl v`Rqi!xӴsEYJK1^C3K ִ!{%ٱ:3.~3سc7]ԩ1lg 3Zز=γJu#B[w_W(K紑ش @ʹ'&"DǴiugq#7̲߳괧3Z޳31MD3tB123c#|մ< Ce=W]o4"[=SmxP.Hr΢δxJ*|sm3O,4n-g2}%ܰT.8c~ǴXӴσ%!o8?8Eͼ)>[ɴ:v$]Eٴ~YP'47b D4'Iݴ9lDU~'#W''E"t5Gxlchq<״a:4uٴ(X V[@j8̣OZ8"4ٴ+%.TFJ/G"ϴ㴛δF6)(u23 @Q S5``D:2V" u3 kV#ɍݦY@ϲyܴK52 V? ȴhƴϮ2ۑi 5-|!>3h"ٴ$2H =Ǐ4z&4x˴XOl뒲I-$1KFm%j ߴe-]K=CDV;:1a@9탴ol Ӏдe 1X2zxXk/2/ŴmL ̉,^ n$4w>5ɴ`(˳U1ZɲxڢO293|l4&A4 X9N ZAQK4BxN[_ډ1]ro4i4><4׳eӡ3pNҴ//Ԇ35ٯ3*cG4%1 W":r3H.l43}2? 4K2 :F8-24ֹ3t]n1M4*t1O294S5\:2먳$3$4EA4@"4⡣4,34˹4r 4zU_3&4ղ4N3x4WP4<424%34]S2j4ij%44?ڟ3䉍4n45L4(&444`4}4?424j43+?4,4 4 '5ES20444֐4zN4 {47S4Jh49D544%5S7I214s0(nѼ4* 454 5On4 434443cX844B%5|ȗ44)$4ڏ5p4Z 4t4z24;54]*4E4;4XK55V5x;J534d#5R%5F%5ʸ5q%4N4߻44R5(4&$5.4CN5z 4Ծ5=a4q5> 54S44M5)45$4 4b4 ,5L5 <5v4'4HN 5'5d4fѕ4'C5-+44X4L4L25=5 444M74!5454f4K5BBl4_44)4=5ޝ4d 5`5ς4GRa5' 54 @5i:A52)55*M4[ 5>4c4P554755W;5O444)5ҟ4~44ڃ44L4pk5#555A49D5%5#0k5(5_?54E4є4˥2g4|?L3r4gjs4o44vB4 s4A5ũk4G34M>324m3qL4{s443C84=35B4+455`4`4D|45ͳ4<4Aݘ44d4\4޼4 P5M554x4]H;4L25^44Mҷ4&l&5`445 14ż4Iv4,X54 3$5*544+D55Vu4\44Ht4f4{4)K4nB{3504ݱ5444P4F4J4m4%554(5144$95(PRz٘4 4K4س2WS5;l44;42 4(4Q44 D4]434\4E5`I4?4r4e4%5=4G_4PZ4)5_W4z4H44r/145d3k4f5qZ4k64RF4D4u5 4U4z4o "54<5]5&4=24c45vS4094M/4|3zYg2c4DB4vFg443[M"3`[;cG3;I̴ʾSӰM31t̜&'ȴ'δ$?l/Wd? y~ZBHm[5nb2Z[VJAF0014㳣,d[e1Ω,F ܿLĊeVRմ3C蟴"p4nDNkӲ323V4"ه*<3a4Ƴd!p1ool83kг|&{bs3^~TKҳy2|Bx#>`Z2#U1^<twmϴ^2Sߴɝ#C@Fڴͨ ?y?ij/sICo"!gOԱ`i3974SOϳR39沾+7iVdz3ZشzW̳]{4YRK3OtQOxn?XpPĴ-?۬A ^k|D^6"$´b3ۿm\ﳬH3bY4"43}@?34x/-*?4k@y~ĴV3H61}4^]hEY4JX?)4'4=40442nqTR42 "Դ5r4Q4@۴Ȳج&̽8n &Oݵ&OQǁKسD4:1Mq3IK0ҮԲCgRNeB"4-3hY3+.}\rDp4/>4B4a3H2Va֣ϴ 2`Y"KOu3ֳe64L4i 2px4cT‹aSN9o3+3-3bpw ]4P4Pj 4Ym2=ҥj94賢44 'Y4T?4@32303ⴞ֭82z]ni`.apqa3f4C5f =4cĴ3lĪ 54I4ި23ij,4e4c 4`5]44b4y4ۉ40;r?.4'2"|4yS4V4i3>3qc44߃3y4 3So3Mز&>45q3Xd=ʁud4TQ3 \4=3"421=p4l:+4Ѣu2<-4SWn4rrhu3Hcf=t4e33i\2)13񻂴-J43 w34DH3t33ٳXJ3a 3R{4a>J!4M"4aS4h#1F4b4-vqW 44Q34J-4aJ4 5;!4C5t&4n]=4494ݳ5U3 5ɒ޲jv44m4l5644[4694 4rl4K/41}3(4-<4a4`5853H5*5{_4a4444n4Ke4Mǝ4iL4 #5ay4 4 4%5(5544 5SX5}4 5 4`n4%5'5Y4R4 y5K&5Q/5,5$.5Z55gF5`5R4.5k4k~44%5W4x4IY525D4`4 5a4i5mD54ɗ4CT5U.5I5M&5a<5a5f<5f!4 ,5uC5T55a*5{4o4 45M5745" 5Q35T4!65us15:E5[5,V4UB5s)54;8585Z75 #5]4W`5\51:44RqY545544(5s#5 f5[44wJ5R+5NU4|4G354B2549O534j4 4P?2S+4 4p3Ͱ4ְ4Ws3e2%44]4Z˳ 53oN 4(fX|3?X4y s'ڴ͠4 3 o:\ aɘENߴD%scDEb@+䝴24ثt}.?D_, 2`l*4-Ӫ5سq'434h>Ŵ+~EΐzݴX+~߳IQ߳ꃴ1./ H 9znhxƴU]# &0D[q{Zp 2κ4r3%# \ޯpr?4S4+۱l3ǵ<$+} 4DZ1ὴ²3(?š|ž3܊33Je4JMBGg3Nئϰr g,擊u}ȴΞᴁzJ [մ>#m,U*?r:m.Ѩ@ԴīV{̹3 )ƴӬ-B8꣟1^X:ٴ 9DWH70 1)wRbykdT  m^43r3!3-Qe.3&b#Hkiz4E24Sv~3#}UI3V4$A4D )4H`ͭ3ω~4A|H4;@4zY3DAx'4J44 u4Y4Q44x_4q^p4B4}4X44s43(D5n,5䇞434Pt4_4&4{_5k4P4>4L425)4cI5L 5[5X#54:5!'5<5fE4d4564525K4 5 5QI4=4J4Z5 44G44BH4d5R5>Nf4L44A4Y(3EV4+5245\H4 5k5;W5vP5u4a;%5B5:4+054O4H4%5Ñc56$"5445M5O54~54-5@4T=4H5f5z 3  4?,53@4-4x4q|44Z[5t5g4wD54J445Ѥ4[254rX4 (5[D45:405L4+4Y4L44YH4]9 5<|4%4" 4t44m|4)*4$5P4<4$5*5'n45V( 5v5e_ 53'4J4_d4N!5c444f45d54=4/5kX 5M.4x444ߥ43 5EP54jH55'4𕴶;5$5N=}45/R54g4F 05~5`84[=4EH565+54eqD5453(n4e5V4W^5 4"\445-4]44958!*5yy5a44I5~4N5n4<449/59#4Ks4w4'"4`44N[5Iݭ4ݧ 5B44Q4AHB4|E4Kx4 4) 4L44Y4|34t44Q4e] 5 ^4 45\44g$4"U4%A4M4aS4թ3-4nW4I۰2c3o3z)4l4L4[49|4!%T4 (34@4 3]434殳4Z4Q4 q4ƶ4:4x44>4$404R54N55 5+5l(5T$54_η444VG4j4̣N471l4t44@5 5A54y 505g4Z$'5}4V4 5:5fr4 35׺5S5k4-344C44y\4g 55 4032 57^4:%4Ѱ4D45r~4" 434 574ڈ)4`4^4{΄4MS4R44G54bV4S 5d4 %4a$4x32@ƀ4;4t44˧4:w12_<5VO4n4cm4m.4q3!'444={.3?4-B4"3E4 744z5JyT4 4Qt:4^/4&H2 zf=2糳ݤEAvm(27 u}  ڵ4B״Ba*]TƴjYw`w| ִP ޴lUx+Ǵ :,:#Ǵb6T"$Դg]8ngk*&862ش)韴uP_3iԴӴ$ʴ3hɴ~ Y*%^ҴŴdor "&,0/tnh6%DrGﴸ2K^w{4#>R(˴޲Ӵu8X=*ZM,}jYtNG)YblHK}Zw?1xt+ Eq54s 5M544T5Q14V5j58?5554G5BG5W@5")5jy45А5K4>yz55)f5]5wV5?UW5MI5|'^5`E5$|5P4=585AB4uU5O5SX54e55(5 5N5XT595J,5FK5=#4z5U55Oy 5kx5V4N4.5H5O4c4 4J5Z5*5>bP5y4t$5~54ޚ4b64{e5/a4N{5M'5;-4,54"k4g4! 5C$34 /3Ņ4 I424^4U04y3r4tJ5ѽ3#J*55u(5J4$;4KB4$%45R 5>q5~¤4W4b4@4TA 55z4˙3T5>4U4ߛ45yc4ǧ C4 mV3O4: F4D4C4N474$"4g3i5'44Zb4 4nMK3ư4و345z˚3\9{3lZ2b4?n4K:jO>4Gc32F4k4`yk4H~3yQJ4x1ZR8(!߲g= 4\\HK- wfo Ķ˴t'Xk3-ڴ)arӴ@3{M;n~$㕳3E׆c%,H&03r}_̴xG)߉2G޴+OzJ2Abijm,mN_ȓ3Eڳƒ,vqSUdoNy. [^kdHɁ˙.DôͭkôyA55B;3;^5xŴOk1L޾`3XIlnJ?)?uRVƴlICqFtδe/PJ08gi?Y3cC ag'+J]kbg3;7wM\Z;8l`ro"v0뀵WcaC#7J`jc^卐LNeip2̴wd&qK2RG\`2:*.SK9rts||>Xf~uUdjpT"fj5 8Q"FL{倵KC6>A&VF[Oy4DMB0`Wˌ]\@uquÜRFč,)1wYMkѱND)"}RwC#UZ8%$mN+J7W3&SO"=OX Y}#s}80d}2 Ctc0(A2A6t[Ѵt1H<+g:Ez +=2LشrԴ%B1, vT@*^7U/kAec0=6He0;UMO떓HN/V쳙0@ɭjT X"k=j%0?fK3д%|0-s4M8jy`4-γ:m3f3/J(]04B4@7x$Yc4)XW)C3:f4{!Yp4e[2j~-4G3'4)kX3 3|a- xm8m'X4t4){ y4(4H4SB4Q}4OR4I(3 35&5ۋ40-434֊46C4+4 544j)64j&4@r64O=4V4pm3{2 44 )4@Ą4Q5;x4Z4>45đ445k4,{4e454R4#΢44Av4E55%5mA55*521545)*5I558#5G5>S5%4<75jb5C5l45)5I5i5KU4\'5'-4b\B5P45 u5J5˯4K 5F 5z"5v5 5_?5T565rɉ4! 5$D5L4s5iu5T5^5fc75154<5)5n(5z4q55r5+58-5/J/5^45v44B:5J5u75 C5N5kA5ԘF5s4?{5e4 ~|5נ55~05^B5|65ZO4ZH5C5545j4})+5q54hm855x4ұ5G5D&5m4G`5S4^505CV 543 545>y4x14*$@5yD4h45J4R3w4j4C54p 4"H44/m3t4O455nv3׎44gN5[ⷅ4^ȳG34="3q3p404T"W4Z4#4s3T43Xf2[4;Š4(p43484"3|3:ܷ3?4M3چ4k3'x%4Nh3:3`G+x3 64dZ4f4˜4]5444:&4*(K4l_3?34Ǘ14-W4pׂ47)5w?4T4 z4g4xr"504/+43P2.ٲr4I94eH4 &4535vu4 c 42?b(3d4ִiFc{J9Nj#:3aGz[?/4䛳D=343 г+3\PGٳ}{ZZcZ#ʆ=vI4IBkv4@Wӳ 3M"Wq3.kre3߃nD3@m;Y74$2uADM3Ǝ 3{4D4 ȳ@~72_Ɵ=kR3D47B8։~I0Y!Lyh|W>qե~#H8ʹ3L:Y=q{Q/]0ٴof봐CSkE-C)&gɋ uS .=Y ?ϦZ$L,:v2(< I0Y|bδ 㴜6ϥ6(JHl1%}}.0=kjI˴K@Dܴ&~NaUWӴ@3)Im0*pk1WI봔.S@ų*+ bѴL^ 7aw6q -O>UeFWo FW<7캶;ڭEX0 ϴ0U ee03fv4[,183D 43h"3f4 ֳ3 3 $33Xuɳ+eZ4j643>c44! 3h,3`2=˳QsͲ8۳iS4tb 4G(-1jm3+3eW3Xy4̣̳I4q+3s<ųD4S4{1??2 3˓2ֵ@4/@ٳ!8-4j3_2 =3ųA4O44^/5u4M464D3;.34Ot2K44RD%3 A%5V3Ö4Ph4>2=44FC3|4l.423=)44M3/4<5844t444c4c4;1| 4βŦ134.+3e߳3rK3Գy~4U`2UHˬ04꤭4nhď354M 4w%N43E4鬳#3{3Ya;4+#4HA3.4J3E.94hr44<3:=32Aܳ 4@34k4#4TK44;4?35iE$3944[44!4ׯ4i4 A5A)5n4T 5$3 4s44#44 44L* 5m44.5Z<5_/4m5c4ʫ4PP'5S.5t(5T4Y4 5R"5M4S5՘$5544hL44_ҳ,5/44Y41 4(4w044/4T%44q<5L4z5܍ 554*45!.=5<5ډ5{55v5|n54 -5Xl4h4;H5 5VG5U15\%5 5NC 55k5K5L44F5&4:445O645>4 u5(/5!\4P:544W`4@8C5#`5a55&;n5f 5'44) 5E/254o5a5.#95Dh;5wN5A^55~N5Ș<5C4c5or5U 5jP5g4]4M4pW504Ҙ5Xc4tp$5t?55O5SV5.E5@5|&e55_N5Y^558!5J5t܇5Bg5|.5'5[5,s52@57'5P5c5e54u5wtW58ڇ5 5ka5N55555!5l5͏55+@5vۓ5U5Zp5L\5:5N}5E5k555&P5U4,5 5$!5He5,5*-55Ih5ǰ\5^565'55[c<5j5 44 $4:5=c95w@^5m<5KW5iY5g5$ 5}5Y5 5&5LN]5w~5&5<<595̔q5,/5Ҥ95p$5l:56M5.48!5%E5 Q5Ov5+5.5zt5|G4/_F5~5 k5J5H5vo5)5Jb5ea5a A5\*554)4F5/5U5552H5َ4/5r65i5E,5 H5~r55455 \5w45^;N5r95'15nU454(>44fn 5b 5I/a5%X'5r44VV5F%54244}4AQ4Fc4Gt4LH55454'&4 =5)5+<445&4z"4456<4>4|4͸454,4`5444ٔ4F 5i43 4 Un4("3v'5%44 o4|5e4144G44td4qh4t4_-4,S42T=Ų (445R4?4F4|4o54z 55i$J5[354`-5W 5Jo4:`5I5p5N5C5E"5m<5e5/505N5,5I54L5q55>4 5E5/85C5*OS5.5H5Ц95jQ4 ^G5 O`5T5B5G]585Z5o*5Ej5m 534h55^I5Ȇ5R4\5h54}G5 53/55I5w5015-,5\ 5f4v>i5v4>5?5Hk44X5zW55254sU5}W47&34t/446434O5N%53 5N5P45b4X74 1gi4ʆ3cN4F4424Y74MO+54m^:4-ΒIW8wBy´_4#7@4˴O,cmN4D[ܴ^ҴǴU㒴7N1KI+ܴ*oW*해#cK %ȳodh27.)ьWB.YEke5) 9ߴKȴ +䡴덴X`Q'_զU!J֗hԡnKydՁĴIa86{슴הּ%Cóմ#WY9)^ ,y2jw@XJBBδ 2+˴732M~aP▴46´'Uqf單#˴Pδx,|vBar:!S3.Ro#4o꧴{DƳES q{ oPO+DDyqr\{2񋘴aއ I8Id:Y|cU4ླw佔ѥ;>V$\5!0 vE.{lᎴc3Y 3Aq3> k15Ł??3=3ڐL8~7!9܏Ӵ/@Oݴ(u ӳaj峡ȶ zUMR ^Y~w#^˲~2K^1ȴթ2F?Ӵ2մʛc]oٴ_<N⳸u{ݡ%y/ѴJ۴u۴#ұ'_2 ° ִ鳰rI1&G3Fػk^A.Ob 7dF3 i} 4"]w4Zv4nKٳk4q.(34(Ub3:4n4gIϥ~G!e2N8QX323d3I4ބX%3iD4 ״KDm3—3dέ3bj2lô,ߖ2`Ҳ`^h=23 곹4F晴434(4Q3{j Lճ7zBb4a4Ń3@2|5Ez"#4Aٲ3жPD8TUz548)3%J'3g4**5惴 ;:Yk5B]пV3ڥX3-Z3okM}3yDP~UouD_6ƴEq̳uR5S ?óݿoʴӇt S  4-^"z]tp3eZ4,|J?1uW3U|Ǵ 2qyu32_S0ѳYx2( )4,$jgs33[BI\'4voϳk"-4|պO{۲lW3<45\^5l䳙 U4VgAW2Qܘ2ʍ4N3wѳfp ϵشfP:;,T`|o@ó~ȝ[Yr&yώ}WKyן3?JX<2T2߂Ƅ2Y3U*4 _w1字3 ݞ4gc4W 2,_&43 F413UV444^4`24Ǵ4a@4Z/4r4C4zi4 Xs4A3>4Jdk3F2Ϳ3?G43LV2o9kK4#4 q4gRq1&Dh/=g4t 2j(h3?nBN4ٌ73ap34^r4]3Df~4V#4A3Հ4IY4a"y3&4W34d374F494 +5P414 5]4j444+5'4652O4j35445a4]5<554 5425O/44[f5,4G054A5v5@/5h4lg5HQ5j4f" 5K)5 5n95o5ŋh555r55A5o5c4G:5șP5L&5-5;?54KB-55d454t57~3r.5654y *5h454rZ5T%5B574*5'4` 52>5>,5@5NXl5,4V544M85a54)4К4d2|-4vI'4 U4$ 5 44\y4.4q 5g4N44s54< 4#4r4\P%0B4k94 _3O4ή4r)3#54aZ4 4Ѹq4%<4y4V߁447|445h<44p4Z\4<ħ4L3r4s43ᮆ33hT3U3ԉ2e4X3}3H34\3Ǐ hB 9/N276׾_'3tϲkΔ'434R3tITP?3ڱXJ@4ϴݾ5yڳU 7+XD4n |4Sm=483Go 4ɗWKK1󭕴H"3ߌ,Υ2nw(M&FG1z34eocP4ùd3T 4[4VX2b_4OG3a.D4;c/> k03jT4P,44T4/ߒ4Ƴ3 I4o4އs3}e3:3V1Е3R3mZ44 4CՍ4۱"36a45v4B3)F44yD4He34o92h3ᬳl2˳BdfдL,3t* "}4qe#YEd㗨DU3ʹ y7v~3n#F }ѴS⃴ u]Sѓ޳ɴjԳD곴Xٴ5ak仿7- J𴝐INc <@ 8)1831*W#4~6K]L -iwŭ8 9#(2qE3rUJ12P#Ĵ$k L8lnbj2W4UE]Uwy4?4a8tV,&^Ǵ*e,R3(*ƴڴ7m̴s˲Z̈/մr t)oVδ#ô,v a)u6>a*4A3(p͌?Ә~CLoHV+QF1$P:4^{.1X-E43 3[34ܸ44I3,4=4XL424D4DXr4;5e444]4y2 4J4B]1H4Bm44*44̓4iJ4/4s4A4;I4T4?Z<33u:5 54|4P.5]4IZ4d5 4464~4?4#5tg3Ρ4e45d/4j*54G4_43d5c5\342*3C4t43e3 4c 4 ׏{S(4v4n4534UYu2S4P4v40{ת3nL404h3[P3XijPg0(]3J5643U'nvYQQc7B4uvS 1-43,B33LM$v+43V1OM56{ׯp 5ܚ4=4.Y4:4YZ424X6"3F3r4h׳[3E4@4 5N]4Qbv@4j-:/ 5:4r:44)8=54I'5GH4a4^443Է4e44;4²44m4jn5M+4',4J4؝444W44ol4ʆ4)4|4R44G]4:4R4+3)u4k443od3/g4(3!D$2}3/43Q*^$4)$ô/1 #4nKY|3 3{1P P2NVnA$<37>3I-54\l 5@2f*7䬳3!3Yj̳s2Sb44374le23^4{4˅163Dg4.4W 4qXN44444TO4925nJ 4ɳqV40q=3 ~3'\!4x%4f3s4L)a3(2V33ZJ4æ]k4#4eP 4gV3Yc82[4 4g3C4T愊4󄊳j3Y34=@3 4u40:*64)4A9-"Q30 43X49 s32m3$tN4?$44;34mS)42h4ߌ4.4, 434244 !5k4y4 A4E5 4>/5454R3=z4"B42U4T>H4=4j63R`k3p0o 鳋q3;Z42t3>k}44?1^jdz>3346,53T3 4?4X3h2̳Yy2HE^*4$4S13c I4M/货`4֛?Ucy=д{(o4s2EgAb= 2$4a474Ho 4~6$y>!4)nAYl4j<42Nu4q_}4-uo3!18Ƴ㳳q2X29ܴʓ64o3N34eo3&4_14Z63gM3%2 /4Z4 iË:4_:4QEO4M 3S 43b3cK#ij'y<=," #0K"P>㮴1s3ɳ]u"4@4^Lj䫳U+IDSL4+IZ33=1: 4?94_u4{cT4^)44623 4kX4.3|4ZS33z4?5a4 K45γ4c!4I~4(', 4бS4u4M-_4}]ݲ-4V4mڱ|1/Y44C:432su34;נ4+ ~)4,{43qptw3v 4AHL|@ [5~:״(QNͳnvg-N3_F%4LV+ 3 AA29m*=A3g瓳h牳.>r84靲4a4-4˙b4ͫ2^Yߋ4.(cuc23f464E3ʳv}M4ۤ&45E.43%4 4Rw3o4޽4vl44%E45"4p484~33f4ʐ3Hv43&+4(44u5(4c44&-4 434KDY4d4R)474}52v4W4‹x44>4@4”4߁4_4i4-5\P4f4r #4j44#413 5c4X4p4:4ы4wDO4Y4?444]44ݛ4d44C4<54 E4M.4#`J4``5395X4P^4U4 +5@44mc4I4V<4>20462t4\34X4KC4&k4+3d> 4S524yX3Wf4E2(p44n+43H4x4gֺ4d4+4$44X4>!44] 5m4. V4ǡ3@Y44ǔ24564 3 O-4r3`4DzN40:444uJ3-sW3=1{ֳa44N4ɯ1ftC4gñb2[ӄ h xpG4b* gs3fV$3UXS4('33Y~44hז02*4=3)38%E84G48 )44W/4sy4F 9.1lE.94{s3ܘ3V5E޳I6a4p24*54344> ,g4l9=3,5455 5 5E4Rf4ְ4_"y4;5|]4߂4Q^404 4C-*43w4534oX433!,j4`4v 4&4O$45qs4&Mmg'3ez34jt4 x 647}B۳n43F3~43 3[44 43F3w4ҰI3-Ҳ4Ų_4+4 4ӕ3L36B4l353ܭǐ}B}E43RT3aTOj!9sEU3]=4˴F3!1Q5х:]̴3d {)*2f K"mI.ry$5-yNj aԴr䡴_3j8-ً:>2ഊG,t%7p̱)O340%Ѵ0x.dմ^4e1Yu䧴Ĵ𚴝<ô(=yb1YԄC= SH&+]y8[2"X࿙{3MOSMg06NR/4ԜFY_H۶a s!-%U*)m ´`'rP~yS4Pϴ_!e2-) )P)oŴtd>*{@%u++_ v!4صJoʲӴS:._ZCR+~(,W^m9D+d-qAO@>u`5pzEvFzyP2{=I=W.xF‚A2FB&Ugj cruRXCSbW@A0;L@YKƶc0)ar 09 M 99s6(\I ꫇pzs2UvӃ &]&SEZ' p*$ô|m_7&Ǵ I y[ycv ~aDB mմPUCGИ!洴@w/&F(Mq崴*i_2:~$ǟ$5&Sb"bC@3ɳx3L3y3tT(ct43!ȳWٚ` 4<3I2W'C35G3$#3b*V4+ôE,~]4kwU3 $VKŤSqّ-ɲʵD˴duKUJq鴳RTQ28̴gU@4 +4q8ʹ :Oͪi,3ԳW%B/Bp]]4]泬Q4p' Oq~[3nXu3kS3EF,M4Q

4P 58 5.1575$93֜59!54|4~w4Kg4e45gH44S4l,5465}t444x3oR4w4n4!5]3W4J4l4-$4+44]uC 4A6ڳV25Ԙ4u85㹶4Gw4奄4C(45;65`w4Gk4YD1o˳ο5dNvȳo4DZ5Z3ֱ3;4H}404k3"4y4_44&455S4*4Z44{3l_4ʛ4"jƲ4U4s'44>54tB4 5m4R4 4 4`n4i5+44;!4 ٢4b>M4/4-4443XI444H4Կ05=4`24צ4NO4a\15T44'4xp45ڮ5V4 4P4A#34Ƞ4L?84T44&4d3T?4n|59 5.44Ч4!4'q444+334q43C34]}&4HC4ܭx4lZ45642@Wz445@44q4434844{4I$5i#54F$5"'5..4_44{F5044ߜ%4D54<444w4[mP5XRb46-*547|4j4`05)44{4kJ535trk4E_:5"454; 5 5=5&55A%5DX)5'(5 575955s442)5K44J3T4;4}4$14{m}z5P434ͳʍ['4E3 9S4204aX3C;oe4Jm%6Y48vq3!!U133`D޳9j4dೀ2~>34/?8'lt443RXɳ'*մKִ)㼲e8I3H ó5b6p/{blϘ 2NrŴb2mᴋo A򅑴F5BB.#n=7 r,+ `gHy#>% }Ŵ[J"wҝߴ_B>TrǴ#<=/p"\)w(!KɮfdGⴔĵ´i-dzLךNTYQ8VQ۳IK޴޳|Vؔ𬤴u<ϴ'ʴs3:Ѵ-O:NH єƴ"}Xiڴϴh](K*`3ʴjmG״Dgx\}ܼ2roέ\糱~ʴS13e^I-aWSA3533D)umS9T+b4!aK{!j~SU3x4ima3,ݲ=+hJz33Ӌ>d*ƴ(*4QJ0ݳQ423 )'&B3Iv) 3Rqk4۴#y#,38sŴ`2v"S3oz2_Ħ,412TQDtY҆2+S_ǘ|3p߲fV8BByQǺJԴw$rʳ`44<>u :AK3vGVU+ S3Ԃ0W%B403nG⹴ƴqX eJ #ִ쇳U'=e(βjsw!3pޮ _Ϭ;T#3s\->3"(̴R12Ctݴuk" 9 f3P5δr7SN,ߴ}fkҴ WΜ3S.@! .62~A2ͳ㵴 3%Px.kt۰+ɪ듐^ճu1;(J&xGAGVAi=ᔴ h yR&ӴP],;2||2|#N烴zAj-մ"uP²0$n*Їﴂ3HJf3r<4ē=%4/ƽ2K?2 3. 3R*r t3OdzQ7'VvO2i2:91"'2,2Mc4V3EQeMd'o4 ^4&4~44 a;4/H4MM4Z$4铳M]5439گ4Fw4}ڿ2ݬ4Oc4f44R 4d44h4]4EڳE{4ɏ6 4,ë4'`4;44,4$245l4߿ݟ4+4C545G4=5_c42y46ߗ4]Z4צ44j43w445|4}^4E754']4t5ݓ4558F5s4w"4514R4 4.ԡ4t4&4d155hʑ4"5A}484⤭3ԧ4X1434b4D4${4Y434w4t݈454ғ4f4r4`:4 34-2_34B4D;2(4|4uT4p k4M}4L4]^4243t4|5[V43364p5Hy3+$44yr4Y.3S?$@4B45g>4,4Pm46m3˨wMt;44N#y3v4ź38l3 4Mb 544A]Vbh 5JR4݇43l{E4y4s43n4 ܳ]44j3744L3<"5 5^384844=Q4j44J$544g4ي4D!5< 5C+5.5յr47O5΢4v4!545ET!5«50\3%?5Ҽ4%5(544 c4`4AS5 5[530+4X4$a>5a54R4^H5i4 4 o4z-5~Ȯ4Bt4 54454;4=45#5N4nI5e44b5 5M5܍44-45(ot4f345G|564p4'r4-474415K4M-3:22K3c4A4ò34464W43݌44n4~464q(4Z4;/3w5D'G4%D44J4c23Z4~3ݲnb4z瑴!%4M3Ѻ^3'4e>23=4?{]4T44"Z4S;4F,4q34438տ45:v41ޜ3R3x4n4"r4wl4 3='5M4-S4c_3;3(4{Ti4(z%*44̽4/4U43,p4374=e*p4y4 V4k4t4xw4/43,4S4&44 44 434244@g)5:Ѥ4a4%4o%444dC42W4Zk14G4434# 5k 4[4-#E5_+4X374x4473_z4aG32H3X 4\4Z4d"~I466q4=W5߭G43\4aT XZ43K3]ʹzt4# lh Npu9<&W313*$Ĵշ2k̎DzKjd 3]1g:3R2"C-:3D,!QPl.]Gx3Ђ`ɳX+ʹ#㳛`y3re2Cҿ{u폴!说"LMW=ߴjR華d䴛;F Ҕaɱr 3p}M@M۳OXҴ^bZ.xurՠwK޲ p:д;?Ci_l174鬴wLO8"R/6Xx2GpKUN9?It9俴kl\{ᴼ7xy1ܧG.BM 7дqӴ@Ҵ槎AYZ"5j C iX}s)n뢴<=qpo~54GӴߴ;bڴx˴tH+Ϻ1daɛHʯ:ɴ5 v!t{ܴL)Ն\$q9ėۭf;dxu($S3`MIvݴqy^2%ZQ%J:^EA @x_K' F78uGM69㴵ִr凴ZcEw)o;63$60ܴw KWCz#iִupyشbզ"#(gL䱴8ѴyvxiIܴѴϰir8Ϧč Brڳ/MtF5 m0Ǵp_մ֐WVٴ%H%0i; ?="/901gk}- ôm崡GҴd珕XU[ҴaP(Q83'`ҴqS923 ųڔ'3wEO30A洿p4HnO7nZ`w44Y526^v14Å4\3 y'4dv=3 9M44-b>2=4L4[(4| 4'4^o4f3F"N#54ϛ4 C462_4.4z\34e33[A143_4"_4B(-45/dH4U4z)4RQ3B 42H4Y{0U4i2Ǝ54D37ͳ)2Zc434Kc14dN3 4}34}z4i4%35_4}4(5F}45F5 5?3;m4p4*3í4xc4[%444H44L4:R4P4=4D44t4B4>4ފK4W44`Y44WL4g{473Q4f4X40]4] 45S4_4ʨZ 4,4F354߆4v5zz4ex5144 4@541^u34W4K4kz44c4#5BG4{/44 4:5454?4k4D554E5R:4D^455~4m4Ȋ455*[5@?44]+A5J5_D4^4=5㞨45Y2X_5O5}u4=C'55J54i655z5+5eyv5u4`4H 557u4|54<35Q43r=<5I+5ELP5X44`4X5>5"I95e4kE485$S5 5յ4545`465l9U5kV5@4Z.5j5RR5jN5m585t/5]X5V,5Fa5O5@5cv45jw5"z5x5'5d[5Iq5[I5У5NF5I9s5`5dV5Ӈ5`$5;5I5E\o5l5:,5155A5c65Վ5s>5'5!`5X&5 5A655=55B5<3V5cB5G%5F)5LC5j@5LJS5 @58 "5RD5g51YT5h4x15T#5qN5 52-5':5ǣ4xlT5^f5o564m4M045z;4H42@-5K5'45D4͗V5 5=5'56 5@W4>4O4.54:45#5f75 45=#5F54m4*4l[I5,}4o4P.5SN45 4&4"4yQ5}4!5!5}4S5(4%4r(5C-54SE5at 5T5a&A5JM5?5)4#4& 4e445Z4Z'5D5K45I51 5%(5 4e45L"4KS54WV4 4B 55 4wP4Q5854y34;5~H4415&4vh5Uڐ5#5pD5A+4T4[}W5S4?85vW45(_44@4X,35`4265?24p4w5 4-4/585B3k74 4'4'L4F4046484ґ4!95#%5C4խ44Vb4p'eZ44õ44r4ф414\Q4uzH'4,5IȳGW-4Ŵ14#I4/35AT^4'64D$2Bp3 0ij3'3lqγ2  Cd•?ߜc]~Ц3 Y޴= ψۉ-E γ|\Y?I3&껴}Ѵ3Wܴ] 󬴗1dTfM`ᴾlD8:.tԴy~VT4N%-Dp:x1X Xɳ⴨$q۠dcz.̪Ey#c 2`af% H67'Oe5I7WfZsj˴lTUT#(] xdaJ% 3bfX[kݩO,|崶T5+uL'0δ! ]D[w1O9"Fr.^rK'jN赴^33e2ᴠ w#9rӳլC̺-/"6䍳-*!Yy\=0 D$" m@828Qgelb c{o8]##3~I d۴/AsTʹ\ ~>ôԴfʴT3Wմ,柴ɴאR UQ ªW)@=V!FG*:p~gaKuSNAq9q#VjK_"}2A)ELd~J0YC[asUqH+EgG&MSVo(YhMA=[>==^qq*$8 y,oq^Vt5Cp1I?ɴtд}%'HHP|pf[N6D$q ;AczYH 1s~@?{:(iW hZW̴>"r6E%D .F㴓0(`!jaZW}HKZyrsJgp w:6%.-A2JԴ-T!cٴOI״ҴG>y^D\kwTHUvhi(۴ɾ_NҴףuݴV8ķi)õc_4b":1gW3eSR]%;%WH3ഡƳQF!ZÈ!矴d|A³Ln0"U3T19o4#UD4ы|lF3t:3_4kV*944Cؓ3M3Ag[5e4[T-3X4(U My4Qg7wM{D7~42gѴxt:j6PÊk) ),GGhoO 傋DteF`-TY4:+43 s3GO27m4U4O4=zG 4R3'P4ce3-334?5|3&GƱdǜ44Ĉz`4ӳbjD3e1Pa$4*t{ֳρ"*Z'*t=J 346{38g4fF&3œ@4U'w443y8C3X4#3Y4DD.[3w 3z4dC4"b]F PD4{(g3[3*cQ42C4== \EJb3#; ?4*4Bos.'4T.v|)Ց2+>1532[]&\Z3"4Z~,&4 4V%45G5&4T4=4[u4]4BV44I3!ϰ40 !v4&3u4R}z4! 43P4i;43%3t©4}4(tZ4]ov&4c4ۏ%42)}3e{4O3/rU\ ڮ4׊KCسxx + 42bU*M\*ÁUpsffx4K3x314N4t4Ie4D 4{4'ѳa-!4}2Ct3+4P3^4R4ȭo4Ň44v3PT`4#'Y4,|'44fĭϸ%4Ho74M4/ 53gT4ep3 4aF4X.1Z-3Ԗ1W14Z4UP4x 42334X 443'I4 c5ȟ2}/W474~154o4A4C4333\4"5f":4"434$4p4M5DI44B4X=5344)n4,I255B4s445y$5 4fz4N4ދ 54i@3ͫ4{"4a4-4 3@3r3L,4R4>ٝ4 5hX4[243~4b`l4ޛ, LU44OB4Q4 2[44h3،34Y<-K46 =aDs岻r44#4NP@}S3h)Q,374EP\3o_40r3;4H4ȋ32k3ֱ44Cg3b -3^ 3Қ4|5444 4]4{Yc\,4px]4H4K4?ҳ184v3 4uI3z43W'41<494n6314 3/q&4ói~ݳG+⭴e_Vݴm3=T3{zӴy𴡿Fb40<ҴǴ!2F3ܴ1+3ٴ;58qg3q 1r8`5%S4Efwɓ,푴3ÜWo?pʳ럥x2QanZn3+T#2Hr泰m 2>wnh4r+H44J s3>.'-g<#4Yֳ3s53$1^4W49zei4 P4.4U3jG1lfB瑴&I4"1َ+_V2(Ri옴xx:O[z~-, Go!~fC({+f6X>شYwgl 43m9V[&R9Hp0洹kwx< ,.Cش'Ͽ L^I2ExҴ+AR4pԳԕ}kz<a7_NMr3L')睳էkȴMz2z ,|ɝץXCު3C3 @(M*O}13fiW#Q\Q)t-˴ ^įN;r>(@iZ+\Iwʴ<&+MX>ڸy4o}UH_<@E㴁mlf@bƩ?᫟"Ѵ\~}Y$ρ#&>m΋h]Wk_G'aW2.|eA>A3`3Ӣ4C4#+=46f44;3]4X\C4y3 4r4iش4j4C4}&5֍s24t54˥34*4i4 ߋ44Q2A/4n]v4>w4zG3'5^444r2 44{?4>84kZZ4 4;/3 44|f3+i4[304>"4_545A+Ռ=5ė4H5"4|4#54ى45Le5!4M35&+55455 z55y`5?5qM5R4*4455725#4r3,;54i4Sx14[O44"565or5Y5Q 4\4I4NO5_4Cub55(5p4Ӫ4w474t4&4+4}4)84R3¶f5.4f=85r7=3(4Z5O(4j434K 5}4*5O5E55B594=,4]4&E5o^4)454p4:&4zz#5c|4u5U5. U5F45K5E3+$58ǃ4ܯ4^454N5#5|d95v45,5C5O 5/c5AV4t@5586@55@V5^74=5O&5p4xO5up.5 5l4J 5h<5y"525'50G55c^45I5#5?e5, 55c4!v5'^5@fA5lj4^ 5 64|4 545޹5]4ZI59^5_"5v5/5Yoc5.S54w>54ۀ5vj65*58G5_5k55X!5H05W5X55}35454 $5e5a4Ą5N5hfY5[Y5-5f#4^425!5jL5f$5W:5^4%5ā5|55c'd5 4?d&5ӂ5&45X5C4C5GN51$5/!5'4Iv5Y!5ݸ 59O5%5 s5K4nd5S4iC5]4k5430G5e343F 5}n4#}447k4>b4]44j4R4iGV4$BM 4̏4#83=74z4,35D3Y4PVW4Q$JI3]bɠ4<3E14\44T4q4w4R3̳tB`?QE1'CX:kӳ-3P :ҴH]^L}64$fs-U俩zh ܴմٳu ZD]Q1_AƘĴ&̉[Ru9E"H;^ZceRtwAtt=!58&3kܴQ"U4M˴dG/ybL5gyWdB <YES=]IJ'V|94M8RƳ)Sv'3Q#S@($1$34}0p3VS3$zgJ4H34AƍM3&43֚3!w 3E4Q4ݶ4Iv*"44948bY4\*5\443`wk4w3N,13 :33*QHy4ď̀_355#3_3cS4k6t2q4hn2HѲĈ-+ճ-4,4֙3r?Cr  n3ɩW4Saϴ¡4ӳtƳoY1{m#4E| @泙a3*x2B>*OGG37oβ㣴+/ȳgU4˰XӴLM1$k{Zөkֳ$.^'H;{3^>xƥ589ô^Ь2zӮG j1}lQ_#3턒e5/2J3~ӳ_4WV2}Sa3`)#83xY1 741Ŝ3/S0ME3{޳o"gw/:oڴUɴ4۱=4 ۖ34pO&4eŴ9?> ~4?2Rm34A=4莳4fsV!4{0l3D3g3(4/3 12743\2%4;3 -4ٴ_/״z/4t4ᥤ4W 3/p3:w3_13P4ԙw#4bs34T4N44=DQ4iɎ4{3x~4.47!4`N4Kj:AƳQX^2/4 Qó~Q37٠3so94Y3óؒ>4R3IGDŽ(\pez Cֳu3@˲3W=4r.՝%OLJ礲۴ԴN,|V |z2\h 4?e~9$[4IC{Ŵ6 ۏ$Fg3;C*]-X$X߹f[Q0ױ >?4t(ִ<x4Q^ 491ϴbt,ӳ)UGI4@peIx13Y e3l3Q"~:bP Zߠ&<48x"4e+ƴ崘kcճb-2:Qq%4C搴vޥL4ݟF[4;(cT33nP鲑2A35ˋ4 4Uo2OW37 m34)c#3YV4?α4Gl244(4Ox4Cd4.m4=4I483=4q 4ڈ4y4;A4v-43Ad3`44X&4 4W4=43/4Y444643Μ4]v2>74354Ik344k3ϨL4`r4ŭ3494-@39P4d4f93U34}z4у4JF3j3ɏ3O4DD곶xa7}@D94ZR4.hBB$u4g42 r4'A4:2c&4" 4˳ӽ¹T 4qX\} W93)04NR$3t4'[ Vu˲}W糲^̺Z4@=¨!?44ī4P4 4 d.g44R44ܳR44D#43,ϝ3G4*y3=4v4|-3n4:43dz4v4b3=O4pI4,4{^4V264 4@B4m(4雷44e!p3q<4J4x4n2p$42]b4 ܴ3A/3y4 44:@4Z(+X33$d4h47494Q4DaU4&ճA4234>2ه4 4uuN44,4N4 `4a64{4<4$(2 O84r4Oy4n45 5;.b4r&4i4օ4bK"43lwR4w;'44|ٺ4g4443q4L04J-5 4h{444ُ[4Y04f4G/3m34(I48H4B)δF}*3n,h7~O134 4;\g45ֳ洞4xR63%FP:p˕l4<4տ~o1[344B-2R3`4^q4a4 5M3`MG3S4>s3,4U734S2S4e4J4H424m1c43!4~,3G4N(4E 3)m4$3ς᳴&44&+[4l3I\G1ݾ2K4F#N4\4M2ⰳR4A 4I4 3/3G_4uMO4c4ƙ4h'4bW3@4fm 5>f4o3*)j?4O4843c0f4*+4)12VF4n矴ڑ=lԳ 3-~c3n4e3mhг-33; 2Лf3-0 4"VE3[U4ȤA4Fr3!43 \4sa724Ҕ4*437*4>g_ $44l 4K3O33g…T4`3:Jm43Ŗ"Un4hg3 48Q3z$4N4Ƴt4?4Z3#4@W9j4:X4ާ4 3h4\4q]474_j+4P4E4ް?33+T4ֲ#|F \ʹ-4hʳɎR4g=4[J j)33W4Cc4mԲ9R_p4424ʼ0p4#e3|4ogcs4ڳ\4{E4]4`4~33O44M4;#3ʮ4D 585!44534=4+4!46}4p l54xc4J4h3 4;4J#*404K44Y)5+B)4{4M4P:43ݪ 5039"4 27lj4‰(3N421N4"4[IJx#93,Y޴E44;.4"4<ϼEN33͢4ř>4 3\2KN~4#S4r4g4BMo4B 1{4[44HG44Y<4\3Wjic4s3Q4Ef4735!P49S43(4X4t^4m2e4af4vsu4@C4s3eB4x2( 4NO3ю4[b3` 5͆3z3놵3N44&WQ4X=5J4e4@44ǖ4T 5'4Cm2wd4л44:k433ۿ3bj4MX4!3^W4~23W44"4o4 J}4[4&H4g4sT4 034Vb4aJ-44.445K5oe2pi5h4%3eo 5h%ʱ^44W3u0424o_P|̎o>|29e4LN$344%0ȳ]4|S4$4S4 F45xg4<4Mu4W4!424c4Kd4s(54֜D54YP0z504\647413E[444&4CI4NI44iٔ4v3IY4|}4`34%ܦ2z43I3xx4q40t3|,4!lA;3Nw+84Rd4ߴJ޳!\5}д?ױi2kl(;Ɨ4Z!ul@r4FI_:-3$f3DC4ZNx103y@.^?3eS3cmK%4&̈3*"?Ɛ3ڸ1$'4{j44x?߰394~g4"43ǂ441'ֳ6x 53م;4R3o4#;4j44[c4F4SV4OV3Z3#:4ǣY4U4}t4+ʔ(>4N4v=4s444G<4T4%H4Ƅ4ȭ4Sb2 l44644^44 5E4634p4M3 4A4Ƚ4 E4c&5S=5bO43L46q4D3x4˧4U-3:444xY4&k4E4_ 5V4+K(4z4~K4Y4׉4;G4_4x4,34x4/54q5A4Ȃ4&M44*қ444a4D4r4i354v:.5 ߴz"4"4$45H4j35OՀ44v345h5 3օ4i4ݭ4lK4ɘ4uf0GR4DHr3[3 m44uE3d:ôRd4g﹤3|}2,3U/ @3M.;4@4*Z334Ο>j%34g1]2lF478-;4mT3<3dzSk=سVk:?^No4Mx_4 OC'Ty,Lc%d೺xṣM",<@LSδ0=})EΦᥴM=4,ϴ G˃ش^6&Ҵ%0,˴2ʴZ3R´_t 䴳4մj`_Ԥ]~K9ڟ´ GE A:ߴYcݴ9;촼wSGS ,-ϴaO87дC崓8g'䩴=US. rhڴ& swQ=T1\(9E)+/8x;D1!:ϳQ+ ./2`3^4}`Ѵ~oVY\U,4؜4+ u˴"hݳɴuTFUs T>i `l3K?p2V#粬S% qTYs"~CC7oө.,hXv2D^4A 9+n|sO| 3AAYд 4 Fu/o&G] [-\G O EW #A+ u0 y4G)ȴ rd347fnwᴘ´ *^ߴ4guȑ3l#|ִƴ3b<11U7ʀKzO:,/ωsд8teдLv Ĵ4աY:Oٴ)n#r贂UŴNLJ= U-ש48ijWԴN&]ԠgҴI0ڴO/혴ӗp<) *L|E^z´4-RfV.I0z$N ܴ A1rRerǴ:մgp&Ӵ  ҵ.m+v84ִ Ӵnkc3+, g;ô23, ӕ7mJY}W?Ĵ<9ش__3cKN^U#}}ڴ1:B<7W  Џ{EoU镇 2GԴ/7 G2B <)tj$O;HvUs(*ecct:@vY+-Nh {U~Uߴ,EB5m9ݴ#BߴO"ȭZ noP SBδ[_<45\8x@D2*|:J9xf\ӥadʴ8%00O0"Ӵp^^y.ʴi޴ݘs\ȴbǴ{2Vq_] ڴLjGd2dβZdRW?紷TݳVwכܱ*{C)xu3ӳmԳazhMOڵٴe1 AtPAy543 U 4'X-43U\R1~Kc44{2 Y4kк4,404m4#4V~r43g1PS3131h48I4B44Ɂ3C4p{4| Lس0`464a44W44k4S!4ؘr44ϒ4sLZ4YT3ߣ"b4:#3ⓜ4GY*3#{30³˳4Fγ1m.4^M3`h(3Bnw3 >4NVDE44@42l3G/α3|D4Ǟ2i3^]3%G熴rT4ͨ"449m33H4ಳdY2SfB_&yAi24dl3Kte3$&/1]48Tl74?4Q +y|+8\84_J.ô[O4͌>2̻`4glc34r3aYAeYQ9 `rM-2' 4Q[U }2,4_=Q44S3S2J3uγ鍗e4Aׁ0۸t4[4Ǐ3P48b4,4i4y3"4R4W24/4=474X4q4]d3@435$5B4 5{4,54i-55H5@ 5` 5A4i5O4$r5D44t!5D45+Z4V54pw4 4[44d|4x1415,5o4B!5φ4i554B4!&5(M54qm5yB5m4q5/(5V55C}4Ӷ4L49444xp4N5A4Y5N5=5m24N 5]64"4T:473SD5B484d4/d5Gf4X.5E4494h85'455Me5I0)5 s)5C;4Q5Κ*4v7584W,5t50L 5!Z5^?44C4 W4]>4b5L4^ 5' 5^4"5Ϟ444Շ4u41%44A 5B55D52 5z5dy5954Iu5BZ5A4{g5n4g5UK5S55^55CE5Sw54r5a}5zE5̩5;5 5=#O5u5Z 5#44H5854a*5ah553o(5Kv5ZdC5/F5[Q+52 5?f5iiB5]{5025Z51q(5Z5g55L4H5-.5"L5ڪ44 45̀54X5l357J5P4,̟4Z4I4f/5 S4#5)I5S[5153O446 4~!504$5\4=A54ń5=$$5¿ 50 5^A4]5|.5E5o&5B.5̝5νi53<55,&50A654c4j5=)5$5ׁ474355G\34(5(54,5/,5XZ44&5ih5.4\$ 5k4z5/|4u4m;5]5%4j4(j3u5i:4)W4P4M4554~4(Wa3}H4:4 4^544148 4m3b۲½4~w3۷3"2P4[4̞4J44Vg[K4'45G4u 4`q3r'4iէ׬%3ę4d/^>3$[)4m"Գ5z3}4G:4ZO4l2&J 46U4z44f۳x 3Zx1U4 4g2,3³^U"64ZI3 dHRE2tq4ZM-}cƼm8a3e}2]t ImTc݃GW a۳?r$䴄t 9:RULϴp*8}Y̳lŒuUئB1 e%>ѴY ($fത봺0l* SBٴk:{J9_q:\NQ2>m~Gs y"T&I :3- a31;>`&RK0* P-SS򴱱0MA>q.ഓŴCmI2Y* O}4 *A.oJdI pG'6ZD;WD+/.FaCxݎ!hLOg)~QB LY&%4_<ܴ}[zAfVXDr6Y/䗵ލ) u'ZFy:}->\δ䴍5ִjU޴fU}QMɴ'aJ]ᴐTEP.`srQʴߴ-5ZioPд&k΍z̴c!%f9Uܲ FhU  ZTD)\[\wδU^Y´:~ش<)#jٴ6%AوD `3 6`ߴTJ9%WK=Ա.`~r kִinu*1KҪ,3Euy;´Z@Ҵ ۴}۴۴'&ɴ*zy5v|bYYnд"b:РӴ)Cce_pM˴۴(Qݳ['hܳhCTq3 4cǴ ܑB=34._4#V'3FQ3f4qBH4ӣ3ĝ4hL4N3II}4{4a 3l3 3=4{ 칱849]p/1L}L󲷁Z3A4Q[萴4-74ÆF4OP4/o2'3n4 F5,3ΰu44Vfl{M!/4??4z)ȳ7z3Pƒ"3~43Xow4ス3e4ȏ jm 啴 33/ټ["pEPti'4sɤ3h4Rò*4n`44~404V4D84E4_4A4/f4E 43P44]4c):342N3Ʉ3444!!3544X484O4;;kٳ]4 525,54"*5 4L{4ҁ5m)45q4A5 54N!5[4F44(C45~,4/4>4_~84c`4v24m,4G~4q4`$4k3ٙ4>B34 44S143O4.~445x4~4-E57|45A.5[4zM5 X4'3445K54335b5754 I4 4C73%4i4M:43844W41541)-5hf5f4x5-_4m}4J:4H4_?4"4ӏ3]^4o5p4Z,5M?5 4a4?KY4T3*3ڡ4?"4蠂45 443 554DS4z4x4344:4܎4"4>,4!35>4DC54~OT45/94}E4kF4m4s^475j4}3*4)4~4N4oҳq44_g3&ښ453G4ԣ4@5d 5v4u5!4E@5J954V34{5sO@4 34L43!44l4Iβ44 4$5c_4ͳn4> K4D4Pc4! 544ش444,#5Y[3S44$c44#e4Cjk4b374L5C4xG$34'G4p_dT4˳y44'4A364z84c)24~Q3L-4 5!4[44q3w4>C4ooI3 435(493k432z14)4>4b133l3R2@4O2F[̳ &b44}!434.674M`o̳L{i4LZea =44gau3/y阴γQ,';z|s/[r2yϞ3/b4`ǎ4 :ĴϳZx#?EϢ4+Si՞g&zV`332Dɴ-b#4ʔ$^|:fܴG&4u3hXN<-; )贳J3CZ9ldm-6Ju{-!ؾX4'3, m 914&K3)aK3)S&4t3274]FfyL3}3ק>?j3 2k4Zb4K4@%44h3i*q4$3k!44o6ddm4>]]fM3No4Hb]kH4eᦳ'|+43۹3Lw4|Ef4c =44*ܲ3E`04{D=2Q4KV4 j%4@3)3)q3i`l1Y &3Xq3)%4:#4732 Q}]2ۧfI?4Mfsod#L6C6 4<Ľ0z봶&kӴlt`Gn)t2˴麴ôz`Hstt{1o^o? ߴ|?F1`ɴ޿vv(̆Y2Siaw#9Ĵ=ޡ܁ |c?Qkە =޳ʹsCN!ʴؙ4"ⴧ3[ִB%4\#@}A>6 4#G" F33P{43;4=_4A|cN kslN 䳾\7uJ13L G1^5 .Ze̳-l'iW4L=|O34U+4}A3hp*4'3 40]`2 4쳋+#23b4Yʯ4 v3]ziʳО33Lu20*3Ђ*dF4#4 u+w4 4̊4c4I%4;3l|[4f=4ۀC84A2xG391=4.J!3>s7> DTT&zށA0A486̚b3)ӊA e\&ߌ4{3نI󷴍iNLR(vDnNlg 33Ӵv?34R3n_枴33t"//^n) mG84j C=8;-Vb,{3lUhQд\5<33m4#6q}VG3`c3Ns{̳A33f/w3rNY333zM&e43禕3`33^qdl-3SЉ@4oo:ͳ#Λ(61#3)4Wn3$+3=!c&i+4@dGyn4+}4"]-*3_,5Ʊ1464 4p3v4q4ܷ3\3D44R5545ұB434N4~W43C43/a5555Gnk44Y44q4ױ4 4KƟ4`u4U5d3~[&544b4U!5 4A535"4"(4e944pt4&4$4472^5F4q$4dEM434\~m47%o`N4}F4}1{4ϋ4R34d;54s4v@R-ǴA43\c7ȳôװ4Mq볝,I4dпf-414f2~+Y$4 4/]D2v4413,Y44.4(4wul4\3c32j}4й4I4C>43z48T4&q 4.W3M45sf3R91*; 4״*ecȴͤ*״0ȴS&ݴC93}2H$h=R0@:A k^DhǏ M6҆ل?W5ƕ۩3wɴ~>$ pNE~#b<ӜڴX%|;oTneDѴE2ȴ{?DʴBs|0419|aN`Ǵ۴廴+FN% 2x¢ BA6kapUU8"ߊ4CE\Ҵf.7 I]Ĵ\cUuǔw!7റ*zD@(&[ӂ$iдr R#ٴ@y*|Yմ<;^U}j&^<>l)Dfq8ӳ-P72P'Dڔz0jQ3 *'Qw>4BmH뚲|=D2Ul2s'XLlt{3L4QFճ=3ê443j04ؚ3o4ߍ2U4'333 sE52#34ty3>4&"3}4ٲ2O4qL4Uv4n4:4tA4 f&4/!ݤ44+494e<4̫ 4B 4ш4#"4%_44oNJ44r444\5V]4⥇4>5Q4E5kg4F4ו4 5} 34Y3#5SQ4 A4!4.4g4 V4X4̸4^4s'4* 5a2b4Du46 5܌4vf4`5ȟ4=5V4ӏ4m4E5;)4@4C,%514R4 4i 544N!5 5- 5484s%5PP5:4^j4 5zY.55f 45.5HE5y545EG5UO544-51<5k?5Q65^)5(5zI5N5R4500>5=%5#!5w0 55n(54GC544*F5"545Z5 I4?̀44V/05|@5[dq54 5w4ո^5Ң4Q(5',5~l5:yo505&x5t4Zj5 5`5p\5i4!5T359T=5p5J4$J5=T5S_575Jg]5 51 5{5p4ts5H5a'w5*$5t55{'5d5LC5I=5nL5Ex5k15~5oT5L2Y5х5x5O5?5'5$1B5 575n5z>5a5\)5_4f 5W54wj55 55\E5!584%5f4}5+x/54W5D,85p55y4bC545y@25˽55F4H3u3-[>5^448Y4c4V5O"54c5ȕ45oM4Ƒx4 5BG44=4 Ȩ4ר4+5-5k?4S34Vm444}4Ow0434#4P4!5׏4?ؘ=4ȃ4!4Tz4k4*T45D4}p4ͳOz54e3IDĖ>4%4Vo֓4Cʾ43 ER>4V4H4c3K^B40l5K543=W3%4,4*򢗳4T1"134D3S4T|,]4?j}3V)(ijG4x^W3T2F7BDQڝ32a{ɡqf.{೟g҉3245, 43P(Yx 4O4I}4Wn:"/036`3mm4ѹ45Z>w44e45@ԫm4@3$4244rK4#3g84~U^4kX}4{2WⳘ3p3, 4JO3%2sU{4B4QJ!_3=n2=4cq1+2Bڳ 4&24q4l3C)~4{q+4s2 4Q63At5h34bo&z@&ֲsxhҴiD\ڝ 3_Ŵ"P;epW^״:< ]6&+#c&;&jƯeܱs+״ÐT´莴u cR:봸 6дsy|^,*j>ƴW5ZyP/85 R#,7ִN3GⴲQIc_vF)Ĵ3)8d~K%*ִ:]&Ls.紽Q񳭁pj贡2Ol}`%osf.q`-۴ # 8`״ nϴڴ.xc8ô)羳c" >MXQ)/k0KszbkM߳p#i'gr60߳Z,:%}8p34ozP l jҴ7ӆ G,R,T_$8X2`7Euʴy6qĴis/[sq't9j:촑{y VALuvBӴ Ǵ@f'0ܴ#1G:3RZ)ߴsof&[U-PZ'Q[9,Ѵ >= YJV3RL:>>5O%+b O}JD+b5Q|bg/co%Q\GxM7O+d .p|:7k@S"Fs$HUV 6w =PL1H{Y3Tx1L2?Qrn(fa ~ŴPZ\M|:V޴$SPt%RgX2B! $j5EпY|/+ZVk- HEdytVvd Ylf/;|620uAĴP2\W(VִI0DcM3c?u&3۴w{lfD6F͛%3z-~vuĴgСu;482kg0ֲs=4H"}Ab/ڗ|.OAt:M3Pؤ k"L;Gڼ2#vi4|д,bv b3΂r4c4 ([4S\63p33'3;{I&Sʹ3̞3UC@0>RC4ޥ4]{P4D4444~4o4(3_'J5~4&w444T3204H@3 424D*74h5 ?h4vP=4E414bb4rTu4l]4l4hw3ĩ 4924>Dv243F4^5p43""4-4/4R3D4Le4)a4m?4p~44&845l5e%;4<4(4HC4\3Ϫ3M44c=|4m4R44N34:4?4`ڐ4#[44g4*4A3F4F 453^ߥ[5c~54)4 4U;5f4U44P*455?l53Ww45G4]m444B4_R4Y4 )5CC55 &54xQ5k 55iw5'4l+5T5T5K52E5iQ25\E5C +5s 5G5-)5<5X5oī4à4>53A5S5o05$%5EJ5m5V)5V5$5Գ4f+54V5@N55 5z5[5*4`5^}5t6'55QJ5 504Ł5&5} 35k5J55$5֤d4a 5aE5@R35f U5A5Wn5]50V5:5u475D 5XCf58f5M5v5:35G5Fw5]53CN5+W5?5ʚ|5s5KR?5=55@5FD5dp5NC%5q5l5)5f +5.55D[5o55=q5N5<5h5ۛ5A55q5R5{5iw5.N5gx5995aX50h5~575 a5r51,5EPd5m.5q5f5 5,855g5x5`5%L5v5B?5u5!h5>D5\5<552c55055- 565X5 ox5-55X5aS5X5S5a5A5nT5 '5.55&/55B5e5%|555-r5~5B5b%5)5y545*5/5^5i5NvI5W55BG5d5mEN5?4I$s5<.5#565f5 5i5ZP5΍5qU5Z{5S5i4B5 "5Py5,b5P>5w 5"y5*55A0[555\54 54%25154@5 z44553434;Q4514;4M4,44f265 e5a{"55օ4I54@4^4(4,nL4I4k4Ŵ4`o544gs4j:44PB54^i5545D$55Q4\R5%5ˆ5N3$5]5 4-4#R4W3"452X4D5 524v4WC55v865A5J4. 4i5d4ri4Pg4gy4_ߌ4x4Q45ȭ5;ů4,5I4S=44R'5k4Bq4)#5_3[44ٽ"4ʩ4.44;+5S4@643 or4*49W4,c4$4#3)Q3D%0Ar"i3Ӑfj;y44}4I oQsdHL44*4"" :3L4B'Z?3'뚳+4-oV**N _L6Wg!xә vFhS1̞鎖&κy3e$xxM 'Ҵ27sR̷v.0˴8,3@lO鳓,Wqf@(|梴jc\1 δL*ƙPU2&QF۴5eh;봿"ӑH&J$-?+4YM͖wA\_H88>/ ;'ػ:$BչD54a];Z_B\r0;/g?sid<gq@;LyRaZ ŖVMoY{wK`k/q3#쑇z{Kċ&L#}Ȝhwxl8vwSjlH-XpCg6v0W8&V{$n' qF'mR#;֔0Ҡote,E t2 W _CiTe1`\vk]K _ӗ]KZ$l㮵o8z a)1U ptx7O,t0pNB&mhujG0!y)2j6xPyYdžRU1axNݯW%(;HP a1M3[4P<dzXfjgRմJA+wϴsa>\U: Dbuzx>+L[Z:`ݟ?q}_s;hݴaS4ZGd1_d}Wa !T[Bh[(d1B-'.GL4IgQQ ~δ ´cF2дZ iH䴟f+mʗE"۴˚,غ<6"޴)˴- 11"}6GQ c)ʴ n@ԴK_f-vA(-ôGM^:Ac bk58{G?v7A#@G4w5I <,F{A~454'z44K 34DpQ4[o4Sh3F3DD4Z4!4?3{ 2 cVh34֗4?204 !DZ׏4õ4B:'4KԶؾMl`O4UkK444 :4Pѳ994o4NzB^44p484?k4)03⏢vڍ43-3G4 ӏ44:4xO4e3ue4Ll44Q8.3$342s3=4g]4X \4 O23G4;#&3^&Ŵ4CXóڱ.2Ъ)(2 _4P9v]˴d3p=Mճ_ 3Z`}]X?Zݶ^`7 ?~+ӴXy4w234y}T푳6ͪ&NڳdD|eFlu#ʹU3wU򴑊jHzCϳ%C۶~,(.2b[δ& ? -㥴-mK'ȴM95|_lpF0oô-ܴ}$ʹЗരO޴ aDȴC16@>5A_\N6(50ִB~nʹI21'p更 2ӶҴ,&ʴnѴ~Yu(n)ˏ[1&@*&)ģf;Ŵ_Kٴ,NNY&44/Bq1ZصX3CI:F0w9H%BǴ 1z& >;{?-X2.{=NI2.KʳlI sSdzOy5.W]ѕ=1{iwW>4mΟFV F1:4CL㕳È#3{Q 4a{g]3ݴ^KմM۴̎1񤴧ԊјXǴ OJs֊mٴTYL㭴O|ⴾԴ޴V,sM9;>4Wϴ}cô랴aԳĴ\ٴyfJi3?䈴ZgĴ8JY)/H״ۋ1ܳO [KaXa )L=C\K %'QF\ȴl˴ |eӏ[DOz O8:m}дbWS"׍! 1N(Nh?`ϳF贚M(ۙ%2Jꚴ^C2B_\塴~b촊sҏ}y@)44l #4hS4Z+(4`D444=4Ad43 d(4W0i44kʤ37l4zG94ё4}4ޮ3i}3F 3M4a2OG34 ɨ4044.m4=34\FR4u4'4vS*3%@4N$43i4 L]4Ď32 5@54hwY4x4cu4I5/47n4۔4ij.*4~4ﳜa3ZEq#4Cy43330f!+o3X4K0ٳ^*4G2q<^s4\ib+4<<|P4" 33k]3nD]3suu4L޿3rئ3G4PtX.B3424ؒ$4C[ `#H̃44`78P4n=GLG3|;4M3ƊZ-*[3)dz i(3\%3d3#Ͳ,37U4m2cH2R34;iSNDx3573),27;f4ٝ 484 1]ԛ33Gô23\p4q4f4_4SC44N31ǯ(44ٍ4Of42O3 ;4^ 43?;53Z44t}R4l4wA4,o4G45Xٯ4Y4z4uC4&4i!4uX5t|4R45P5o445>4 gI4S75-4سC5FZ3K4374ֶ4].4R4-4g5G$5~4c4B3~S4w44/4ɱ;4-64ʴ4RLq4*51#U4~547E+5׶)33 <2p3Գ'2:˲74>3k1>K~Xh}9j`n463y:ҩ4Ȋ4G[2+4@M3~;EG{;THJE3de4H3Cw36cʲr484`fd4}H{3AԲX4{3d3f1OM3*4P44 4؈4%5~.1N540 ! V4*o3;<4c4r&3W/442Ñ4:4P 434UC43\4P[3t7ɳgPS1K+vjˏǎ4R$j3PaE384 P7u%4S3up;%Qw٥2s4|4w=WI.[H<3tѠᛳ_γ{ l޳0\-lݳRf贰3徂2p&ؗ20 4@ ?3:RJLU3y2L0!34?32`3_ 4ֳQ/_V~.hK 3 I 3\2}-dz33eF(.%~4m4Q3y)4ahZ4yӲibuFp33Buu^!93n{ڳ*O=<2'13&46z@ga3ش: 15$78 *b$k$pie-;IٞȦݴ<趎>]vP}V|BΈ5b2ܲ/Z>hϐج#}_ȳeh"ճf{O\9lUϹ?p״e9ڴwDC0. 4-*Ihct|0 NZ>s,3,91ٯӳ[pH&EeW\`ӳKa"o43Hݴ!T9 a0>3iĴ#>E2δ<3U*ǡ'4ͳX"(δf:6CMczJk @X.H39U/ݴL0?ۚhG 6ļXw3qδ %ӴTa4вW'hT|ڳ%cuDf9ǴG\gb3R2uk䳁2ǴAFv4@4(̭0 ӊ{Ό34|O=24Et;22Mr49V"ɇ(]3i[K4k4]:34=4U3T4 43D4整K&3}34uj=@=59F4!4}4]44C"44-,~43E"4+4Kg74dņ4>4rv3434%4Nu4C4u4ͤ50`3ӫ3143h?4]04cp{t34$L4H|4 44虑4*鳛9534|4374'44 ]39H4=(4cZ3Bv44 44f3>J4vS@]4z43H4!@4W;4&4vw443V33q4I4v<4` 5/5z4%5*34h3O4b?<4&Y4&4м4,4?Kz^V444j4/,4т55W5C4ׁ4lE455 5ʤ35H5j4_5p{4^4454L2X44b24`]3_4544r4_49B 5׌ 544&05P5na5qs41-5^54'5 G54m4]> 4v444I4z4Hf4T4A4#5$5=R4"54qd4Y4%5|95[4K4X4֪4r>44E&5hn3Ӭ4+j4t5^44IB5o-o4/2d4L0534{ƍU:594i44,4s4#5#2u4x4E5C54hS4n4B4V4HG3T>44G43Z炴p354$e34@3Ó3e3G23 o?4@Q 3˻3q3^4z3W'43uԟ4d3id4&f144>44w2{¼2|α"4433Ju4@]x02Js3i20k4ek14_43`34W403R45n45G~4k>4/4x3>a4jF4423Y 5漇4S4244g4g4440944X494)x4x4L48hps44h2&4 3E4(44Í4۳h4u4y3c4544^34 b3>;4Qo4C3X3c4M3f5F4`S3)k4^4[#K4 `4\41rӎ4T 3IN'4+54ވ4<4G4c93444}B3O?j4޸~443O4h44x3rk0d4@Z4u4JO" l#74d*3i)4444Z#%4#7Z3jXr?34mes´' 鴈3Η-Ǵ,WiYfq@3x2yҴͷG]r.ySv᧴ؽo{ .EKIșVL3 4)2n۴i`d,!# eɑs5>i?w1QtA%ִ״>vEa#Jï´ph)Qi贠ێm4Iq:2y# zUIZ>)WǖOH(Ehȴ)qe/HהAt򸴱൳pe򰽴꺴p@ݴƽ>6'qȴ ` ܓ[δ!wCTz<W>u-rA_K괰hL2ִItɴ#L"ᴡIδ\ܴ7дDGʹa~PմZߴ" FFO n츴д!ppŴ ==aS%u'k (Ҵ( (8 vϴ2}UI13hSF"cI*CѴ<mQ{̴Յ`6dմ۴,ҷOĴa.2N x 'Ny3WDM(4ӗ [$ Vhxsލ(4y, LȈ˲Dɳ m!'3؃|33 K4!Nr-z3pe$4/s3{2JM4%|b33@[zt4x3hs쑻44!3(4M4$04C\3 ԲtP4 J5C3>G43HM4˔G4n$2鳴4@s4"( 4'r4:4fvY )N2*%j63P 3}34%`o4]i3_3h14wA3nI4Jo 2>3m3/14Ƨx2a3Fq2Ѫ2P B3Vz$4 4m 53K3K䚛/V-UC4THU3k4G17t331&ru~42&4e4P4m3&>4y4m3^F4b4|23404"3Zg364c84 (4%4o3Y44|[J2T4KG@453Sd4K2<.6C3Kxe94 4{^4E4Მep4x24Ѱ4D;4;44k4H55"54V54j)5 494(4M4Y4[4B5ۑ4U4444s4vG5545;54ܱ4 532Y,4Y41)4a4!54-45qg4-4H#543=]45Ȏ4n4(5\r4w4lh4*4|Y4BM44C4$a4s4H,i434:844wf4;_444~.4l,4g4m4eZ43%j43+$4LL4Ng4O|~4'͘42q0 f4b38}35a3̑3})1838@2d3e.s3Q|r ޳TPn4aKuP4A44`3U󄴥4 E4h3L4U[4`qŵ4̬45ǚӍ5f04h?5L4@hN=40 4EK*k4cb4i2 5Sw4t)484+:z463+pHƌX3b(4He:4{[2`ȳ444tu%4G4m 4X}4پ44@443|4k4r=4;30-534f435|s4w4M34$3/5(4"5@5%&5L505454c455c4"A54'55BU5u444Zo454y@E5+4#5?4Y,415[?}4G5 5/kF5+4Q59E455=4~44(844&$5v4L4t44.;zH5Zt`5_4_F3.4$5@ 4j]4Uۑ4b4g4ڲ(33vp4q߳ 3@e5J3Vm1@!3r2::74X 0X38¼5:;4~0B^49P\MMu>XI4WXՊ4Ş1N4Ns3fE2"OkȶT"d(=3X9B z3]8qEa{no+: L)4734u3333Q4iL4b▴372-D3i~3x3534@23K4| 5}>2J42 4"t44A`K4*5xJ j4!384ܾ3 5Ch3v4av3 Yu3 5 3U"4GÂ3<$LQ]4 cg V!4%2R`mA13 E3241òm5P8 Zz6f:U4,30ϳL3׭?ݴ73g?g۴43_3ؤce7@$4 _2>B3ErT t3ϲwݔx. ʴBoVb13Iʳ302Pf +3Or4c I$R3Ԡ3~ 1٭7l@4P4WK\ʳJX2aעI8 f23VĴ9S\3 36Sd44P`Z 2b\v3_c4}43!p10M ꐳvg4|y43L03F445[ͶótW봅۳VZ贋_=3̴Kle*)u?4d0t[&δm˴o\ޤc(Іv3Of>fB)^mZk=ٴJ!sDôV4҇Cĺ sQ4!kTbʴW0@␠ٗ *4/sKLY4ƴr"13W*r3#594C3`74|?~4.3 64ҌL94Kk4((47]G4T524344⃗4`Tu4p0u54>/3]z"4TF4]3@4]L4#3ҲG/N34=Z4L4d24米LS4GykIc=b3kU3/Ik4֩3 44FȲt4 %v4{+3C493{FM4M4GW4=Q3U4"3>4mJ84 3˘4IL37{3c4[3j3%%4Ƶ33R~|G54KĬ3V3!@w4C4T1=44ݱWճ/2ⴵ>}`4w/\ 3wy,4J3U lj2jMO0cݗBYn7s934$4T2}bsӶ {4R04B4$24@RC7E+4E@3׊4!94/S+j3b{ז~2ϰ=L"տ9ԃ0ߴܰ342W4~FWt3 4^y42- 35,N3(3ST_4 P!w5Pn3)׳IW"카sy4e 0,kX4)|4h 3^2 413n4@f *4 +U;Y113x"-4h3v443C49D4sF4͌.4粗-h4k3lx"4b~M"3 4xAR&4W2 4x33aB%˴4zJ 2r2R[r3je4Ma 2rp33a0L3!4i 5?34M4HO40%!4}2t444rk4m2>$14IA)4%M34*5r–4Tʵ44;44!na4̃4g2 Y4.4w3 j34}<m2_ID4IX2V4(h4e473<+$!`8d4|I4E3a*44ϛ/4B@4ִ%@!<+84sdHpVlk{O-qmvݴ\Zrִ*Dq[p@ JUzzQ Gԭ9O'7`2'5G,Z[r{z~3;V3g1, 9M3v³r4d;若iFlO$>Q4ŴbԴQxJ&!Yݴ2697p~ʴ?^سp$^7P}㙳0XqW3< s4|1k6rO8fi]6+$vӭ:92 1,,[3KT>ę64Z< 0 ʳMDQƳk<̴gF}L4g[Wh3;´`G4~23Kt@4N44f3AXt44*k~4ۻ-r3زȃ43g4m4؊ P<3Ǵ$3 >)3pt2&Z)4[ND3';"3+ߍ(43 3s'4:3^/2lrp4; u[4'%ʑ52 U4#"L4E<3@3,is/24 4:Y4Ef"3'42474 n}`p~ka64a#A441Y[\47pC>4+D4d'4P 36=ӗ(5& $3;4Qd4#P4g4xNs4@ 4*33>44z4EAϳ33 W2S4q3\`4o3ք;44-4W3_ȕ4n14В3?S13W34g344L4,C)β4 QDZE 4C+1@֡34 44굹4f4455P44,33I48Y3Ll4}44-4:453ت4ː4Q474454m04sP-3yӒ4 z33OI2I 4 4ˀ3M44L44.434p444l4_4H i4k 5Qd43M474|:4,ktA84ę474?i38 4 4"m4$~4.4YF4V 1n4B9mD5z45[4*44u4K4@4)3l*4X43=\443 >74f4e#W4M>4;tS4c4ݪ43i4O5Vpb43_5ɮ4Y4H45XO3/4 )}#N3Y23r j4127+'3"4m4"~=eB4)׀,3r53Sa3<44m4TU3BQ4 4ON4_3;4dl3y41ܔ444NZ4S40444^40"54 Q5U42$j4'15NN5T4i443555ZG5*05P4o4w{5Q5s4L4454eL5S4 544~2F3r!54484м4hZ46$44344%<53m#k4+v4T5ŕ55D'4 4v7474?54#4M33d4H4353 4 +4x~S2`3 D᳹.г"W|4Ƴ W4PwG>ٳWI:4g,X89bis5><߳гvHIL7-΃Z3 G4g‚eᓳ wմѴ|YYJ+cBM@s6 GC~I´O>=: bqM"t,? 2ȿ5*0{7EVOcz6c@'ݴT)cyڴx\3$%4p5δ^f'WdrF%O[δE _2>0!pvc# $մ+6ѳâ~n0CuĴ(೬1WѴIĴ\M"临Sֳ᧫A곤ʹ 3֩94vǴ)8zճwmBhG9*ѳ!Ͻ4+(X4W멵O| 43%GвvT3pH3x4:$2z $:14ne<?4r!c紴25 fwɴK6}r෴K08B ڴt[ >ݴT7_5O" I ´K=O35㞴ɴzKӴy)f~⎴̴`yn<)wkX&1eHx۴m(S(|O&`d". 0RNE a"7n(LR.hoYY?'Ĵjo9o1GZ 48V 4Ֆ∴õ3ݘ4HJ4f4ԲB3zMx4_4.G4=x44)Dzwf424644ij.I*4Ч pB43Ɍz3[ZM4 m?ǴFs93WU]2L 33e3q$43A 4X3b4Ɠe.4D4y34m4qZ3EײG94qJ5C4|V4ק4u4b42n4'~C24M4_314]Y4C4u4m44UA45!4A1q4ˇ44*Xv4'k4%v0̗3 4842+!54Ǟ543415Ş45m4WA44r"3o5rv4B4f"4+44k:3e3-+4am2T0hմů lK pI#6Ke- ?*#-:B0T脴sN)$Mk3H δİ_]|I .KgXv:ӴVzEش5̴ⅴKESu9f|AJyi~Ssf^´3Ѳ L"%)/O;ab''p34̴->ڴoI״cQ60\6uԴ3дWn驴H3fwrnҳ>XZ֨6䴤~ɴ^ wܴVcݩL)uݴ~=Ӵ Ȳ;]t`i}s?!f> 38*}d$Zڴ g4Ҵ Môj2lHL?ok؁X{ .F洠 آ*֏4,3ʴ鐳~˴G63W0r/u ̴p޿N]芴*:Ulʴ.ٴn´ⴜ\}KK.[ w x/WPLZeδPOH#G.V&&?FtdVő!=[δ R#EUOP*/# Ѵ!'ToJô . pl˴ زW۳&pma3г/035ʹhų:3D@ڄ4yADk<1Pא 2s3r3/>4 x^2 4.c3 Zh2H3nq<34A/U4\;H4?u143jҰ4m9\4؁c3,3N4w4 ?41i2P44]4_3B4d4C4U142444mXȴa3%(5E3tH44#404Ւ/4P2Mw44.834(;4󀳩#2i4,k3q5u4~F3(s4d)34d3( 3hv4͊4?4.Vn46 3?4343/426 4(3m94q1 s44(4I|3x2x4x3ɵ3544ј4ik<5"ճWk44:ǖ4Z<4JO3+4e494444`i4JG14Դ4/4 42!KI4ٗRi>4p4ѥ^2=9/HY3 2ϳ+ 3x?3S40o02 b3}04豲O&4|%4d3 4-3cx43k4ejQ?v3h4]3W$423eR4T4(G Z#3!f4yi44l4n54bzJE4zj4"4SP3BK44E4@43ey4w*5h3|Z4.2F.ru4똳4 ^ 4TZ4'N34hz4Z445O5X4Z{>5V44 5u35n44<4575n.5N4ei4tn445 5u/4+5ؕ4 E5ŷ4445H4Y5޲4lN49A4k@4t4K44}j33k4>44r94 2G4[c5_T4 3[)u]4H0 2.3>3 3Ȳt4s2ʣ2NR4D6VDk4%3K-I4@4,3 5ҹ4>q44ڪ4( 5V4g545$5ܒ4(*3;44g4n,5n45v$544T4544;4ަ4 4v<4h5k~(4bf414DY44,R4U33Hغ4@O4>ٳ4$5:4464474G&4s3G3!4!482S405)P^4845͞ A;d^4gl 4. 34upݲ3HoΆ_4%領fͲswJ߳W3gۯ'-Ed36J42'64"Upa252 54[rƮ1)]jh@2U 3fg(֞S3`74j?4~c@2!}겅Ƴ4Me3'64I3 ȳ#|2ﴦ*Vҿ4P~c 3\HWS$\.4 +IK:4k3vo4̳y94qq3nU4k2AvvuZ[%T4b2b3" {3Բ4-+ߧ4v.c2Pw]-A|4o;3/!3S 14oټ?4%DB.1l #(4hEc@&4?,44׫4Y64ɛ 4!4۲iȳT4DJbd[`dzlRU4PG !? ,hX4&bӲ#O˳ؿB43JtشR1`"3iӣ3_at볤[`3|4ܴ%Q4C 4ٚ2^3f30e32ⳳ4hT](4s24F2t',312| 3lTJ3"4bPZC9]W3Q0G6gS᝚Eq`2 DgD,"̴sy.N!O܏_ӌ & (,m#pش'x)B&|e=Z3/<3I4J M!5*4{45 43_4Oȳ:2?ʁ4# 4 3363gx3g߮4Ų4O6& 4Y26^@y1q4+Œ"i82-~d3c41;3g4Kr/}E2y_.~4ӗ3̖4! v4ȇ4 `4Mk4"@4us4G433!\4A4,4F!3?4;4>2>533<4Lk4Dp4b3V 3û2+2eN2՛4-4TA 3 |34n1@3^gCiE523.03z4Jm,i3n421+44m \43BO4kgYF#u4Bk4DzT4=!4ͳ-_M53^;QF55#ڴ 4sm.ôe{+=@#7@EYv2e}}%җc"O#Wh7;N": (Dut4 d=}ܧ󻴚WFǴ\| jTȴ[ȩ~#'ݴHH!}3j ._clɴqʠܴQ U#p04ڲI@ż3f1l32bU3:ݥƤ^D3ǻٳ 15n1xi4 ]4?4JNbr 3`0'4ed_AwQHp2fu. 9"\7L4ȳZ3fF3qo4Q;#e$(m2bL ˲7ۣ3B3%dw/ X 4N紳(1d 3 ?дb3 <,4Rܴi+:J(;iٳu-_[+118f-Yo]7δ63Á[>2kQ´)oTٴeV# q&K+C2 >_w~4'H)9ycֳmpGyXųIѳĦ74@3u)4c4[G3lC(*T.rݳ!2V3Ѵf3b|K!!3J[ձ6 )'i4;3\Z 4h|BQǓB+pw6)%D43-t3BI[hߩAKѳ٩x풴Wش?ʹHnuK3/0+2҉21լѳp=Wm5if4˂(P=49A4j‡O36\^4&C453$352 44X4:ֲ2/3\44!3l4%4'4ە4k44 ;l444X2P4833J4p4~phd4xsp4uf4hh"6{x;u44<cn2_ |4ze44/2X,3s-l4e4J4aůaH 8@R1@^ⴒ,!4e۳W4}>2m(g:4}+@?-3?2eb:4Үū(4~n4:3Lj4<ņ3#1(3g@428 4՝3*d|3ų?h'n24F Er!2A75z\&4Ŏ474!g4 4)׫344ea3$2(24ׇ4q4D4|4 5L 5q45 4G945 4>:\44#O3 4505 5y=5a! 57:}S5V15315E4n4D4ވ4/5a4}5%5d"5&4z4\44?3_X4ݟ4j4Y4ֹ34'Y444‚404?49j5`4)3#-3\4r41Z 5}43[5*y44w[403+5543.4Ҕ54y4d+2$HN4 k4B5`544e4/4*M4W4ν4l5^54z495ï43'S44W4B43{4 544'*4a 5+84>4̛ 5y4]#4ڒI`4S=4~J4.4ʲ3~8`4M34x4"#4342Ӎ4˳ PU3H4)4/V*y4;y׬$4[@B4't/K3|-4D(惴s4m<j4E3i >4D3MTԳ 4E84^ 3#3"u~4[mM4UНH44a>4764OW3_V1)F2{3Ch3A[39292@.YQ3a34Bz!2=4$bx{+Y3y!p#8h2AxW2* 3-3 L(%N/3,3 %c4MŤ14 3 6\333}wn]Ka2k \.ٴXs2yMUݴ!f7ʴ`AǴ(nrZ~sB5G!.5uH1a5I s ST S"tAQ Mo{ +  &BC봋5̴D ځ>Y=6l35_giz᳿󾴮DѴJ?  pmy1Ƴ{TǴ~RKolдZ&+ϴgk ؚ_ʺ\괒h$7<%/ 3Gk0ʹ-P78w̭h[⤴1ԲL޿xд14$361G387`3\ME(4 33꧍3p4:4TL1Nk4D34bF4;544s44W43{k:4`۳%1N3+{~4,44-424 r4k4ZU4-(l3B)44 3P4Bq3Yf44qj4-.[a34^2UT4˘c˳^3߲g4`4]G4lA4Z3Pc4g4b^L3؏44!&E$"44r]4;3S4T4+4-453 i4C4]e4n54444`W3"4294% 5fQ75!424 w444ؓ4 5$;5A4!4 554.4"P444 5n4-525^<4"5nKX54-5%5 5,4#44ބ"5F55.t5L4?44V5g.5\4^4P454Ux4Ŵ4ƥ4h4VS3',5r4nt44,4-4sZ442D()4ʳ4~3fd4sO3l^4%3443s44g4d4"4l5Z4x4 4C 3' 5Pdg4ۭ40G4ٿ4}&54?p4?44c4*R45G4384z{3<34=z}4P4443.]4Jь4n4V45=g44I5S14!ʱ4!4̠3(5/a[5q5N5L3 5kJ5G54%4l4.4V85{3j4 4T4N4î44t74&4+>4(W3`44Z4Vб4R4l4?d4ҹ4v454f45453C(5<3F!4SS4555>64|qa4z;4l345L4g4_545554u434=>'3/4443y44d 4 4`!5a54`44X/5Z4Q5:15 4~4s48u4B4h44 5Kt514?H5a5ݺ5 5L'5\541424_44I4a4m:343 5J4w4М42E465544 4|4KF4 44*4,d4os4!C54g 4j4 J4G4m5GV444M 4--N46˳P4264FnNɐK3$C4v\43'44;*3t4^P4EX*3?24fA454E42>b4c2334]˴Rͳ3|A):434e)N3 3hENW>4J9aٳ"U3q33 Psó/N3hE3 4S/зU4d3[B4(35h$t3 c.4}3,2سfD3-(3xH70638\:Ua2T.81i洀66#2l( @#DUgӴ$˴+e糧AP ִٴ)?鰴?|[D,a:t@:qc蒴 \;3uXB3%l )Y3*;5ycʳS0A2* w6:γE?9f!44@ɴ;G X4j}T4,1I´i+%42[3m13.V4ݘ483S(4(3O312-@yݮ3'.Z4B(4Pwƴ$s34|h3F+ 4XABRN>L񻀴9t3 [hXmӴ(cW:޴inF´QbȔ&׈av #O7bԅ3k3Ê3bAͳ@C_5ӴOP´s.lk1UNV ȔJx WƵ@ԗʦ-.&Ǵ3*RԳ"6 q;}OEܥ+ 괗_/! z9ʹHδgu[Ѱ858Y83 +SoWn$쯴KYYQA["#"jMA4'Zw6`>kqcq2bd~Q$$fJꜴl84ݴ0{-Xf@Ń^`GҲj/*p%GwU F]4Az5"/^δ۴63/˳ꁴBJ 4_ĴLE4`rcBq3|u#< I46>3Uʹ̳ڝ󆷳nih$޴Q9Je|ڴ62`v1Q0' Zѳ! q4>pj4wԲ F7Fj=@賂#Ćִ,\Al5ݴFjǡTⳤS4d4 #q:\ܴ~^)2մ=ESȴ@5 ƴA] -z w#GɲQzK$̛gE]7. -Դ]U󴏲&K_m:&˴`@i3 ޴PLS+IJc]ҴD <;d!״4%Z3}b|DJ^AAgKU'5mT1 m%QP=' ,ള5UNu@*Ý))ʴ#c,f M/Sv:i5I~)bù.MLw]lcHw'B6` t&K*bD|ђ;39no@:g3(ijꊲږ jش+̳F b3%#~FX33:s4[3:4r4[XqYۇ45+3qԬ4:Ņ2X30444<4kJm} .41c4zNY4ޘDs4@34f4y3Ŀ<4}n43!23[4c4@4'?5k5y{4Y3 23T(4[4n4 Ņ4/.4f+3&4;d34?4`3 5( 4W743P4( `4c-4#4s34kM}4-5L4O#4`5yww{ 4vsIj5'4 49iD55L4!4UZ4:&343& 4*4) 5e4Ŧ'54܃5Z4'4O44Y055e4t540 5m4wP5,4!35C44uw4F5z0584!5N55tk465$5 5F4&5'05$05l44bC57R55+4Nv5f>4B5H5L5f445t5J4W;75j55u5Dȧ44;J45j44z54b 5H$5dE;5F56?5p~4:55935^4G5%4Օ$4!5344 5w 5U4{4r4~4H405B54V5,4Z55B5444I8#5g5?55P25z41g4f 5?5_34h 5{5 55C5K14Y 544*F5Ȩ%5 5*$5f5T5Nc5455R~55_f56p5Y55$35XRi5 405cJ5^5|45 5:#5 #*5A5ޥr5։5j5k5s25xC59c5Y6555,5r5y65X55]5U5of5|5Yc5\t5-N5-5/25ՠ^55Q55X5TN5]5wU5)35Yb5{T5j5ui5y~5z' 5V,354O? 5C47%5yF5s5375,544:?5p\5>5:42m5Ť:5+55 ĥ4J 5s!5c4 45c`)5<5"F 54z594=15n4}45?j454{45475" 5ǡ054Ӊ4>5e4'15ި544LL5:54P4X#4a)4No54M4454P44y5Ӆ4 ?4:b354#5y34Eu4r[U5Ћ444ߋ4`1434å57?4O'4O441 4qu4玆454Q3l 54J5(.5o5E4k35*j5v5654\5ZZ.5ɞ.5U4N5J5l u52R 5q 5m45ke?5J\@5444A535)&5Q5m5!T547E5~5qA5R5144F4o4444%u4I4Y5˟3Ǧ54YO4G4s2P2 '4`H4I{`4^445C4p\4$424BE3 3? ۈ!4'y4C1 2I4Mrֳ[4neC4+볷ȳ\ h%l4sLسr;2ÍPm `%V+x>ٴ Q\z=дĔx4մ{7yV BYlKe˂h^@p];\$b|뽴ϙ6?ڴc&&ۯ 3c:گJ`X0ʴ>4ES2TⴜѴN]״Q?3O;}) ôJFr0VA4W=5`;\ĴܵФYoOYf[N]g2qI9k3BlP-JJ T>gC&i.@c<0dl>ZhH.hoj88G^} 9?dq1F! qD,l|i|DA"WeBxH ,L͇TZ" J\05 A{jU;AƀUQv*V62KfԴ*n|`zB8$JCm,R,{.)]ȴ; 5c %$LƑ'r߫CuG6N;>H5/ ?"Nw+vBŹ#T/FL#ZqуL$=(B״_VJ|nk-K@9֬*ɴ5)G<㴮7Q AݴQDBKOǰB3R{)gwxbY=V_n.䩠WJ0kq|ˊ+ z(k]醵YnڤѺ#W]C+:T\2дz2MF!{F򴜰}He^&@ WCQ&vܴgDKص*'9l QR i ]7/_^ IJ$Uڴ*Ŵ 32`myi3;1,T04^0"r271e$(F1MɴxO#uʳ?kaVuɳn#_g뒴l `3e oJ9[崥1Mqr6E46}۴ܡ3o-ߴE4=6^妴}ϣafLB3ӄl@3t]3B6~O/3;*:EӒٴ[8<.Q4h@3óOZ4* {'ٳ\y4@(mK(n4@743WA|$Y#44}˲` ΄74363wEx"u3t2nҴ3Yhkę#4M42w3Ѿà40{[)B~3@">T33;I4ag3^,$03`3=U3y71V!4jP4/d42fV1&a4̲If4[41Xbs34 3R1I394Ӳ/3z3kAJ403_3YV2>3rWz483fMs4h4( 4AȲ84d5T44Pd-h4+4. ճr4242'l3+m4̢3k,3s4n4f54<5584!b4yi4$!5~45j84N4Ю4V54{4T4W=r44,4*44Y444W4v5j3jT44ѷ44}4T4L4 4"4s4d~4j[5~45K4m2`4.4Q35l44446`3U-4^>44y04@44541^3S4k3+me4)49 3\33{3ȳw4D^15;3ƯX3磳4U4144e>59~k4xy4B4~+4f;4z444Ƙ'4V5u4X?41))4Ѯ4g4hwT5v4+4l4)4d3'(54Rt3zL54JZ5404m4&;5(ʸ4~54W4Jv444F4Of35=#3S-5L4,(5-m4&94)z>4|P44d444Ď 5~{5$-4'44hbH4e4$ 5$4ԭ4h4 N 54O4ϳ5[ 5Â5^4lZ4M4 4ʆ3E;5E%3ں4i4w4>4bʎ4Y^484|J4@4I_4+ڊ4w 5bL4-4c24E45(434$3v4R4(t/454# 5SY4${Z5U4;?4g4,424 4n44o5U4444E4y4523ř44w4UC4IѲF4d34p4aNȃ4:4{b4L3=4b1D4&3K4f4yMwN414*e"4qz/o'2~<\4N4/4`K4%4޹Ƴ\8&2*JU"}`ȮE4d3\\B3+|_U4 Tv#gm3󵐳p< [+34cj3 5( -cv,[x3QEryF3б!泠.4;3L0 4>q3dSo3Jѱ83V<4vr#3axZ)Hl!g dt Kq0E,iQ83$.+O."u7e*X4I_N=s9FG(>Ʊ4-ij2VLTQδǀܴ08ʍ1uN3'U聃Q5~l~!ഐLڴx,㖴˴]CPO06ӴvϳdzGD杴~8Do#ѳ.CٴO߲δp.soHyԴ KfmB =!gO6yl)k2]"3︀7-ڴftSұ=L3u.]~'RW3"耴L˴W-_`, Ty3L*ܳӴJ_2jQ~ 捴?2< @2' 3 e7I KT|go4Ѵ].Ƕг Ҵ'y%8b9􆴋 ,E3Z%dԴr+<0bs ƄH\6X'2 ^3ƒȳ/4$ 1r Iߴ1g32VXԴ%=?3^&ߴvտ 2*< &̳O ⃴,ܲWއĴ7'Ǥ6,9>;J ◴!~_'%GUs=~qӄt16A4L<7(Y2,1v*_gbRa9YBd1Ĵ 촤. P´`d;KG6`Mg$SN b;lC煵gR.=?ٴ@˴@%Z'>kp5 孳Tϴ ų8-Ĵg b3 XOYNܴć 5o,"Žt3RE7/9Ǵek37ԴB˴D7+2Ljh3Ldz8F/"oj"Ӹ3aw3 Kƴͱꑱlc3(y!3#әBd/px1?!Ea3'ꩴ؉~(ݴJQ42cyڳ"̍)3]©4$Ig1um3f/X[R1ԁ94eG]'45ʵ)4s4}nR3yҳꭳ34L\24#4ܲ@}4Ϝój4y 4<3% I4 4U 4aB4E`3Ȃ4MV5qQ4cw(h-4j'494l4JV4:44]4<4._޳3s˸:4+26E4ղ 43 4r3gƇ4ų4ôtQ4x³,I޴3\vG4 3vϽ3cc3+<"{F3γě4[[9vZ4poB;4/5̐4M~4e353w73X}4*Vd4}A3н444ލɱ4< E4E44--44䓯44@3T4"㊲ʆ5Wg4>44x4v4}ś4C5R5T4<4w)05ZC5@5+404@5$4)44W 5W5(O5!%5;%5 5?5R4x5W5c4[45|A5@5d5;5^nD5?U491z5֙/515%51 515R"58(5m&5r754m5kڤ4Q52d15>54VZ5n$5cD5@5٘4-g54 5KV5̅5= 5g5 >55O5$v51v5bI5p?5OK55 \5N54*e5 5Bd55Ðk5{P:5X 05;85b5#5mZ5 54o\B5,4|D5V36<5e855%4ce 5ᡜ4 4,3v44/4ə4v G45# 5+5w5%4Q3493>4j 5ۧ4 4x4ӳT/4~J334g4^s;nL^4#2do4J !ڳI\3A!g`dZUi hU#\4˞244i3܋3 q2r533댷4˴4%2ŴSh4fH44,D04B42'4F4M2\P4D3yh4=41e3Ɂ45R4_44p4 U5s-44M4X,5%f 5#5՛K54zP-5R494X4/b,5f4t 5m&44Y448S5ǫ442N454<2545:245۪#54KN5b75ry4 ]455@L~4V 5W!44Rb544v4Ε4Wp4<49M44X4K4I44<45,4(5*3w5Ғ4+364 4X44KP`4\42*W~4ۗ463>1i4{]ݲ#4Q3&/E4394ݾ;44L4uK3dU$3mm ӳyN4޳X4X@}40O_c3}k434r,'4 4_=3"4 40304 b/4t4N=M4Nk}w2>eq D&xq49v35&3dٰׅ24,4/R2X3yVSp7iz3uR7Z3'40X48̝y3\hᇉ2S4t2/~d4'l4j4: M3g30 3'˳K*K23ILӳMӳ\1OF3_ <4p̉2H3ʖ2ȴd2wlPTR&3=d!@0׍4[8Bu4s W3Gd4!043 ̴(3cju4(%25ה3Q4{ 46[ H1x3-('L޳_30貧344AWbUH1ϙ 4/7⚴'ON50{3Z 4l3)bN|4fr2;4m[463R3%3:j4wC4Yڞ4.13/4ROKI4)t23y4Fm >49@& 3`$4vV22wנw2Ɂ9H3C.`PҀg""XE1WƋ&gѴҴ23ppx23yC0qӳ랴b?B5dN!u8m5#j ߲44bS4 ~4dr374N34@3n4J3J}4Ƴ͵3{432\~9P4`q3724䉴24C3%3r4sM3[r2!4U5 6rA3; 34fMFQT3(kSs3m43$,474p4<(4e4~^E13 2똤3%5+_d4O̳bL84I44{3Q<5,2Zi4544Ω54s4E T4C44[5h44l5ڻ4:|4PX44a544,5]344 445v,54lI5#44)4n"B5Sc54<*5B44w5X4mk4Ύ 5Dc5Q5,4595e4@h4T5}4`5544:4q4743S5L4>s444*%54֮ 5S4u45]55845c4)54Vss444=48d5ܙ44Q4|5z'5.3X&5ܽ(5>5V4#5=5,4t~44!4qǢ454|44ɶ4H_4u4xD4(44 ~L4,4+43/M4G.324@m92MT2M~4!kWu3)bN_f4y3+=ioRU*د´<3e4Օ2&5M2GP^3[c=a3&4AȴO 43o)&4-3X3 3eF2^22\&].'P3c)4W̳\43C4s4,s8dS`3唴G3֮>48Hx47_4u ˥32s`4w-4Ҹv#N3bn%D,D4M,H|?22A3,۳1t&4335!/X.  45$4N۶3wQ4p944YQ3\ [?dpJ3lV4Zb3G(2s4>4c#4o.4d᳟4L}34@~4]k!5k4D36h423|'[N4IW1z r34 4J4a4\4u@4i14`b<5R5s 5[4S5`]5'wu4T5~ 5b:5.555.#59[57B5 54l@54S585M'55)5ƺ`450F5<5H"5)5l 5#5N54B54R:54 4F5'm54̘5p[5"54595`4T5)4#5%*55d+5r4sK5Rr5 5EJ5 ;5|5GC5}U5=K5l5O%5 656/5yS4C W4-4l5Z55>54 <35r:5 5oE5Z5*5"5l'5"5_}5N?5a)5;4րl5 DB5!5 ˉ58x55D/5jM5]5W5Ū15h5x4&-5I5~8F5C@5=5_ 5ڦ(5y599 5U_`5@5H55U)5&f4[&5L5l[4+44[p5t3,5j95N45 5j!5R%5b"45f405R4In4,B4 564"5sE655;34r5i`=565?4fx4Z5L4wC5V@5S|4$=4P_585b43K5s5 5v5ycB5\4YB5e5e 5_5 "5Q5U55G5q45yXZ5l8R5~_595+d5G5>:5L;5yk5*5o?5`H55e4~O5/50y565aJ5v5%35a5%5Ս5w5E/543545K5oT5[5<5T5c65V4! 5N'5A5T5@B5 25,V5(95 |H5k(5T4M5- 5@4$45Q4514h45!4P4l4gL4*^4Ɉ 5@3a4ywkd4D479 3N22Ls4:H^38\33힔E?< ^Ŵ24gY蘴Q&2Kش̲>Bg :$&/̀Zwj eF AɦB֝A%jv A6I G-Z?ôf#9xߴdĴLU ԤՠiR0uz!1"NEZ|/A,_n콴^rW.e3>m~uXyX̴ķ PP <3+MmS:?shڴ~]ִmз No V54K\l봂E n?@(@ǐd"ٞ_`T{0Go%uﴺBݴ"f#ݴXq3ŴU%´mzسH|2GIgi H4'S3 +h"~k>53M{|=dX e ,`MI4373G MŴ F({6rش(C3\k '0ޞ2Bm]ϴ6!v)>C*iRHY3KW>C+0qqKmhqdb2dMI$^S,4eH2˴f 5Π2,k ӳP}'/D컳g޴;3uj"m Lij鎡߱3˘4X{3I R3O3<2c4_gwؽ4k33 4кq4F31Yȳ+}$4 e4)eܳ51c}ϲԏ41 3sO4J3{4L3i0o4474D_4 o4 ^4ٕ5w{4 }3;a3Pp4TC<ߏ4|z 3C4Г4C2I3OR3pk4Q3L4Pi[4f73ӳ.%R 4b M34~w4"e4K2|N2oa3@3[EC3:^eQ>43ϯds}334T6U2-=4Fm34gE494J 4p =O_4$c J3,>43v˳M64`3`2JsM2;&P\e9ͳ 3VڴT_4Od,R~* :zg13bމm 'Cꃇ4<,n4C[368v34fȴ廻W߬1 ħ4.4-B2P4pN3aP2 EH43c׳bhM2⒳OӲ84lg2f4S߅쳮m3 wʣ S2(['_b´4;.$ 43w3JWE}T~kΖ *>:4k3f3Sʹ{A3{}/e0ش4۴14NDuh4x$Om?״~G4紡=΋_ˎT(򴯾[sbV.0ŽoKmCYtӫf3Ebk77] 3|럭7A,DѴ,^Rky-w 5@~ e*Q (״l 8<*r;xZʰɓ$3Bش 쮴1UqS3jVlU3 +CDi3m3ZW4~4X3c4";(p/jo453-3s4+|5U4#44 48043+P1fv43R ?4"4~4Χ3' D4?3p]4ץ4Z4a4h4Y44hz4k44Z0#5$464i44G5o4 449W4o4Ŕ34M"4@4>44m4|E4Q44隈Dw33k33`\4}`4_0f4Y44 5U 4 5Kɬ46=-4ͧ4444M+53"y+5z3E36RV444ȋ44;44*i4M4G4(5q 5Q4,w956e45xW4T545>4s4!53J54=d4& 5bQ54005W&=595BG=5bw5|:4%5)'-50#F5:PV5!5Z5€5c{U5 s55S5L5G5 5CA5:5vm5pL5y55"55:5v55O55s5é5r5Đ5|Ө5X5]5ͣ5X5=5R5pc55{5m55gQ5555+5,5555\5t=5f5"̞55545ϧ555c5C`5{|5g5q5555R5i55^5&Ǽ5ax5t5q5 5,|595"5S55N5#5V5~55x5@2535 5~5{o5555q,5d`5'5͡5555Kl55n5G55(5#ۅ5Ɗ5<505݀5q5_5#{5^5s5\5Eu;5J5(~5bÀ5{o5'5*5Fd5E5g>52545?5[aI5lP95[5WH5[5u5r5rC5r4m 5l4+54I44/ 5+]5(@4%5? 55e45 !5445 5n55]v5K5$5o4`"Գ354W˾3mG5H4u32*5.4-584V{4 4,ճ4ȶ3Pa4ЖR4CX4E4A4;qALEƽ4bV4 4q24gS11SZ]0?4z2qA3;(14}j3(Y/1 >44r'4 z[2 sೞ?:74$m3kQ3P9r% ¯!uu8$w4]/GL3 ܴ3r=QGwDԳL0igx nor3L p@tݴh(nŴ>B'gN4!H󊩴}wϴIhܴ5 s6;(5 pUU!xi `8zR= @׺-bЧu=ZlmOUЕFOp<b9+|?Jz1|kH+=l[-7NDq+6{ɑ6lJе?s/页ϵiXjDs<:]%ڵ駵Huѵɵ_еΨ *̵qյJ εlñ׵ȮѵX"ε е} Al˵oε1ֵxTյQ䵥ѵ5H͵2F=ܵ7 NY> sSԵ4Hӵ͵f_0" mE͵pXtƵ$w79o"޵ܵ:Qw޵fWP뵆:ɵ޵k/̵|[@;統ȵu%ѹݵo3 ~PЦǵ׵9:vMµ[IY붵^õ#P"q rD\aa]<෵XϐD.6ε\Bƞ^\BKY鐆]j[;t?J9壉#lU5Sn0(G ]¾l`h0 WkOgQJwhЄ$aѴM;KR"&z/Eט5L-rNM 9)ƺf+<)ܴW活TԆJ64y## %0./)5,j>/۴į>yĴGԴ!zCQԯV'oP #k7A4ƴ :4ҚK S{U,` #BP!˴H1])p3ɴ\)CpZ5K9-7|o4&3uŭ l+4-m43>3:׳,=4fM4k 4k2T44xزw440494k24w45"45Gx!4r155\C4254>~4*5²4E5$4r5\54uu5|5We5h=5X4N55-55z25R54,5`vA5X4~5^`5N{5i2565H5-5?5U5rA5>5nQ 5;;55H4P5#F5W;5x/5op555VD5 Z5:U5p55?z5w5x 525S;515r5?k65<5,5_P[5u5c)5n*5mG15B,O5UI5 ;5{4D54ϑ355D ?52-5r04q45B44H5\4o4f04Z3mt43TȾ4x34 54N4%Ib4~M465v4 w%5t14404u3J~43L503F4}\4Td3O5 d3a^335:s4 H4F4(4 4ƴ 34[4#o44X4x4yi41O޳M3b34p4w.3^3S48.4wx4V4'14G3c44 }4W/2443a3Z4432ǔO8r os322%_4+74uEn3^3+ɳ[ra \4ں30W4H3X(~7,3Dzy3_]K4h4f6u5#3?){4dfE4}&4(4w^4f4t3!4U2r3454V"z4糵#&2 p4D4(̱s4 3j/OJ5tKٳ1%D3k䴇K4z4ѴgkKn,ݴnIQ$e$>II^yyUb37 hFv3 2d.+2ⴡCAشTαN|# |ރIOm 2TıV촓ou+'sXb\Lrw5hܴi;Ѵ- ^SN<$Џ &E0ʳOb}5One/xr|δT&24V%ֳH4~4чȴ@y)N׭xq3t=Q)ƃ4ȴ4O.}]FÕ3 a4Rl| "{մgW3Hgbb4D74M|9N`f3km3#ɴ+ ʷ’,³I7i4_J3d5Yʶw4y'4g4Ab4~4]4'֥U432 }4|'4q2(4ͮ04z4h4Dd%4>$44S4 4\45\r445u5ò45T4m<5kT5"5v'55q5MX5oET5`45B5Ff5+%c5~5$5GT55l56552J5)P5m}5t;595I5x5H5S5"5y5N52T54 5FE5Tg5tU5{G5\5 5C5i5{5rX5 055r~5F,5V5yK5 {B5L$5>)5k5&5}5Q]W555M5'55[5Yum5655h̔555I?}55355oM5d˯5)55c#a5&k5]p5O5li5,5]5"M5c5/5/d5C5<5O5r5qy5>5d5O5@K55_65w5|5&G5 5Wb55~ 5Fu5͔55B5I5q5yx5Q56X5@5<55N%5ey5h555<e5[5`55?j5$5^5;55tNH5OɈ5\55SJ553I5Ni5_5Q5wŖ5c5O55}5uZ5<,5b/515J585 H55s&5w5575<5?X5Ŧ5@?\5a5Y5 5wT5Yb5=5\055aT5y5 I5jP$5iR55 o5 W5DH5Tz54o5!H25k5\5S5 5=5X-y5Bd5c52_5o$5N4uU5"5l5h4ݶ-5&5E495H[5B 5o4 ~[54 5Rg4x4EX42!5]34d44[J5(844d44٠4EQ4p44& 4q364Hّqu4 43mR3YlT34dxU4RT4g2 4AO:2yv 43ZwW 3+4zH~17DQ_"!!eKa RдM+f:XCI\ jR=^I6 & ~+R}p+;+"k24% h5;̷8qY5V_ypqVR僵.x[{{3 &iyCKڲ?Jr@ϏgEŵS⹵LƵc➭%ɵwصqε=CUF쵒u1@ƵQݿ εDmsյ޵9Yjϵˉܵ SZweܵ,յ$e"Ŋе{4S4_?Ƶehӵεy9*е@: k ⵰еvOa ǵk˵ ݵRgԵOz˵еjT3|Cg굑Xtqqr>>嵾굿 )1+յ𵳶Y{s m:6t[~SqBHٵW8 L T+0VIU^>Pµ WﵡQ= @ .J @ k5w6%TƵ㭵LѵOʵl7.ǵ}еP˵~ȵnI^Eֵɼ39\)h?6H8˵2͵;µM&)ƵﶿMUh+dw֖Rq>1]t斐(隺)p][h7b G腵" UO<{'j M@bq@H]'wE 7䳽&4`(2;Fl1ŴE:Ѵ7 :ӆS |$OLӨ 3vdz*T33+z%)aBQ4a4cI44;<4z!314峴Dd-44~ƞ4"t4xo4ݵ4!]44P4Vײ5b4}4c:5444 l54455޹44o5954ii5#,5GF'5T45{X5n\55&n5l+5kL5R-~5-40A5M5Q5.5!K55}5+5rH55$@55u55J5뺖5{5 L5 =53^5u55t5 j5,g55*{5555ъ55#t5o5L56C55Ͳ5#"55 $5ί5~5355{5Y5~5NU55?55,5w5k5=5b55Q5{;5M5h5l5~55K5rJ5R555/55!5t5G25.N5B'5z5o=5555 5ܟ5=H55'55h5CM59r5z5255555y5|6W5 55x5(55†55Ew 6v55 65d5'555y05G55505,555=5z5к555"5555y5255h555w5'55 5Y5I#51N5Z505.55,Z5(5~5ߞ5ĉ5Z5]F5(5"e5p5K555.5Ӷ5\5գ5٠55!54p5T5< 5B5k5ю5Do5F5w{5d'5sR55˵5Y[55=5ƒ5ʶ50*_5=[5ln5k55t5$5.@Z5"nS5I4e5$O5tm45#5]5?C!5vZ5>5g.5t}5۵4.5jw5A4tP4&!4V4544C|24P4~4dg4623I4P|4̔N3T4%4ӝH43*x4$kð\j3_"ޱ-ON 2aW2)M\w4DI3˥4q\*3cQg/4Vw?q dz48˳`4;ق3YY3QAy3$y~{\ b2Iڳyt޲7br1´_9󙬳FQ읶Al_3ⳖִIó(q'3fP4]4ɌD3C{Ǵp!loNʴ^E ~! ד `dƴT;]`0W:VJUr9sqSJ# ?@D$[Rx'D:<~F,-핵xVC^^vIhNyzH/؆: 쪵TFoqcõ*ʂnFI9ԁ@fza>\' Y'iAhhd缵8ߧ֓]Kw?`0m)rMrx7et-rKe}ׇƝٛt;\Ȋ08byX0qLj4q/^RMÎQytqmZY1|A5VG+<#*0{|3EӈCM(-#E8%~Ͼ1GPNʹX/!{cMIThm71)YE*Y2Pʴ&F2}*鴾EB{4:<-2>laq&l+cy3Eh0ݳ?Pɴy2żU3N{oǢvy444M]4/3I4tP4454)45W4#4X3e5c 4wX4"'444N}544È5&!5 4y,5[X45Y=5Ӌ5OE44i35p4l54g4 65?5>>5h48M656rZ5J5{w5x?55<5s%5P5o<4Lq5|"'5P5H8L5J'r5 d5Sb5r5 525;5zMs5Z4I55X\5Qϣ5FV5W:$5{5.5*5:5q4a5J:54[>585`5#W5M[J5(Fa5j5Ug5r5V_k5/5x65՝:5h 5w5,5U5~5]5)45$n5L5>!5t5 ]55ǎ5:k55Dk59565D5i5A5AE5b5NJ5&5[5S5T555|5i5b]5M!5J5R5kKc55A5y555)55˚5!r55O555W5^ k5ș55轀55Vn5( j5T5S5a5* 55`c5vS5_On5@5RB5575 5 5yv55R5H5 5y5'5W^G5uP5@*55G5|5 n5-A5Ǒ5ߤ55u5aM5hl5[5VR|5H5~5995#s5KB575]5VT5:5h5R^5 @5~5/5n5W5`5(4VL53X53!5eL5-51*5L!5t5!5q3j5Q4lO4X5,444IE5:4~34;Z/5B͞4C5b44559f40l4 449͗43զ4qp4@4DZ4k733<54jB 44Υ<#Mv4kI4E3'd{4d4J$5`։3rߴ^|4h/44ד"4,h} :4[pF3R0'Iw4e`41Ƴnlq4:T5"FOy3_ؒq82Q!߿z]@ϴK|߀H$jwó.N3X~k]g Qʳd 2O^=%U08HS δh/Rд8壴$XiП ƽ-2D a7;GQ y~@HxwkoE]H%5Է ~`-2 5wf#xg!f .1|_λ.PO'$A \2J$(`)_ 65'C q[Ʉ6AKJ֤>,^f~'Z30F1=#YJQ%!0Jܷ!Uo&4ru"K%4AOuB6bZ9= MR yp\Txv/N$!t4`6#۴iPvV}(MjBl޻ܴ4 zoWy??^Y2{@Kq2GEE)n?TC+}3ҳ`c0q2^ESU2F0N$4Iv3+´Ƕq43m鲹a64 Y(4j쫞4x4nc4+LU3;4;W3 A4(04 wQi4uҳh^,~44*ȳqƅ4'y4c)&93J R48 W<5hq3&y4?bx4~3+"4ftA4942_4 4Ԅ4|D4C4K4O2T44T5[ '4U, 554Ӵ47 5 4 x44 54g4^5]4E3E54z4i4& 5@?75G5^4u4U5,45$N5+50m5j-H54O:5t4UU55:.5G5)5ˈ5J5\59ڱ4"r5DB5%Q55cZ5c?4"5yQ5Y}?5|5#=5$5p5/55f D5;95ӧv5F^555?5p55z3T5|5͚g5o̘5 )5' 5YG5SGe5'R5j/5v5$5ꚩ555 5Y5W5ɡ5+55|i5Q5r5;55ܝ555V5=5:5en5br55k5O5m5Ѵ5{5+5.H555<5w5Ѱ55]5{)5;s555Z5y5@5&15@5J5ql5>&5ظu5>5m5-52 q5^555蘜5Jd55 R5'55fdT55a5T5i5+55Zy5[55d5M~5Ε5:5BF5{5Ir5ð05f5[^5Y4y)5R5+5m^ 5g5xK5N5D'5^5^A5 4v}5ǯ\5OI5fp5ozu5a42505Y(!5/(85N5345R5//%50V4 5M5j454&45I5$4Q4 53422[444Ԍ(4q4I4Z4;4 4K4ﴼw4I4;3\44 94-4w4ĺU4Q5(5T4XV4z434p 5M4I5!u4C4s84n [45{475c4-53,4)5^H4g55㞑4345H4̽3 x4ڄ3M3944c4N4I?4>E4j'4k*4a44Z4 ٻ4{bD3GV4<=j4AN5Q|38355d4ٲϙ4t)3;4f2472364W%ҭ4GJ341賓l3m4%4 δ@4gMɴA940GB#a2ѻ(ݱ'ȳ3D&W鴿Z02 uDt4=s ޡMt.@ o,RѴOD6]uBi뀵3RsUR)@W #OAq!4|BФ㈵Ցr-}UWJU<$ÁȁTW34q ØYV}mjuwT ɺkInCZ7<˵B~Lεl4^9-LDiŵ4=)u0ǵ?#򩪵Vj͵㵑+^{g ֠xsٵMEI#b;Ю1Nõԑ}AysǁŐȵ@b'&&>LnڵRkoqi`؜w%"MmWCz!˧OS8W˟zR I(+Y8ELuАNbhi1Ry U'3u, u:鉵R8<y t]g´6w2Z@Nco%+#PlsA2 P$b|;Z6kWU݉QB kbJ &}ʹ)+N} wcR1}1ٳ3+a FWyIQT4|,A3E4F&-4&xG4w4#4(54,9444;5Ք484݆4-53`f5ҡ4S 4i45G4Z$4_j5)5k>5K5ډ4555~5.455̃&5sy@50/5?565 ^5>5_cj57U5+|5#X5~8j5u(5^i5 C5L5)E50pe5Ly5f56Q~5~{5{5z4ɇ5wj5#5 S505M5%5;5'5B<545(5%45aM55x5jk5̏5qQ5d5:d5Մ5;5Y5 53K5r5È5m5J5p5T56n5G5Fb5 t5*5iՓ55"k5G35Ҧ5gd5ƃ5i55ڨL5um5551>55?5N~5Ga5 5 5߼45s5r44?47 950l4$44W5 ^44r@15,404'4T 444h4B@X2OD4j3d.@#X4,$443B뙳{4Vv3?,+Gѳ?l4y<3J2-CpJ ~(zwj3m25?4г x9c8x_6z$ nAvĴSIjSM}մ/<2N3 r=| 7{bZF&֥PhôjP&C[贘csAO |Xl54~ So)}P4L#5}`iX" @q{B5a\mN=0ٓ 3̂ߴI-dHY'6_NHa2cﵤ8c9sϵ_vk^wĵmnkk; 1̵1ʵ &ƵQojеXG+̵rEȵɯ8˵*wܵ4ƵԵUŵ1(bᓵ[ɵh!jXõZ]Ҏ2}ƵW0p<2q[r~aՕNYo|rDW9aA!g7wJ4xWfpZoDcߔw8dM8Ž+W=q=@9FY!h?I IGU+ q/NV[ŽO2ŴcJt6!N)+mʹ ۴Ie;R*ch3Gِu%&d74M/+4A}1OX4W\Ŗ4 ր37ҴwE43 a(4O43AP4x4륃4x 5~54F)"5"Q45e9544'4 5.4f4 {53Z5R4=f4O5j]/5Ye55(5Z85U5yo52/55,55v5͕55l5,5{5te5娊55~5%m5ē555+A5]5״55/5:55O55Y5o565j5rM55955J55C55-Ƶ5O5ŭ5O525t?5@545:t565 55ط5h5K5+55u֦5S57;57575 5#5O5g55C5jy5,%5O5"5j5] p5۹5 5~55d55 5h\50u5h5-5ϭ5555/J5s5x5Ž5l5y(5ҝ*55Piw5iT58a5P5Ģ(5v!J5hN5k5͊5w75$5#5`F5];5Wk55x 5 q54s54=r5\5M5r5=Em5a5Y5ȋ5r5o&5y4wP5{%$5MP524+4H[5xG5U+O5g44v5'5.V4߽4h4Ӓ-5 *5a/4'4=5d5ߟ4'~4m4h44>J5IJ5h,54R:5d5f]54A555J`54A(45}4Ƚ4%55+5D4G5s45n4B5%5g4:i4*%444PS4G4\44/4v>4Ѣ4a=B%P23ҧ#x4lȴ硴3+f ccM/ԳMJ ״LXc }L 񥴗&ϴ od342䧪c0rRIUYhHJ+VI!(<܉61lE?uߏuwSW2͵4Zv+zewhL<[3Xf٬V4^4Pb4`4)g3mQ4U 54424l4u4$D4%G5a4k G5%42|4&445Μ4F45=5y49;5X[45<-5]5 ,5W/5|5k5?5w5(>55PH5|5Q5wd5Ue5i5`i5rg5]5x5s5e5ef5c5 5s505P]5"565K5_5{5|555 j5NX55'G5W5C 555%55#T5^555N5r51U55Ej5y55ߏ55/`5p5$5 555_5x55^d525K5xD55h5l5^5+ 54y5Z`55Lɫ555Í5 55> 65P05g5q56*K5O5W5.5p55C5_5I5o5c56552556!5655+5j5^5d.5͟655`5J56"5%j5y55{56 O5ޝ5j{5l5)6' 5q55i55eQ545xg59&5x535zr5ް5C5 K5#55³5[5l55 5ۛ55$55܂x5o5rW5]5@L5@5࠘5 t5E5I5R5}L&5355H5tE5J5puB5J^555h$b5C5ZkZ5Ӷ5I5i54T5]5!5F*R54i"5bU5w+5r5j4΀5%M5(54655׫45=347%1]484?$4nŪ4-4YE4R445F* 3ǚ3A4g4 3YN/h3q:23l> ԽĵGݵ`ƵKvxvµ6hĵӵ 䯵$i㷵۲KBa# Dȵb b۵4ü絵Pƴ0Y;kյRA_޵ZȖmq"^쵀Q[ ƵZ_饵h_$s畵ʻuތவ!O꠵ wvp[ՂnJeˀAv9l6m:[mjD}7P*ϊ!/ %ei r+UScg;{1Vwj)$W9@Y3״JSEK 7Ú2 Ĵ(]δϴ#zD2ܴ4wߥɴN83J8Qd=X6Yⅴ{KM83029ɜ` شoǦ/Us`9F9cYrŰyu~2,ǡ4@'4Ҏ) h4-yΪ2I303Z374`332C,34K4I5E4}#3TR4-4T4af4%5Ҝ44555;i3 5E 544414$-5觲4˪4G5 5—55H5ި4b5nz4O4Z4kAF5l4j55;Ma5< 5)4<5( 55`X55-5ʤ5=Q55,]515b\5T?5[75 J55l555_525[~5R @535 5A5%5Mv5uO5}5&W5f=5255}50fj55KP555WV5@KX5j5DT5IB5q5o5~5H^5555Փ5[5+5Ȩ525P5{v5뽥5(545>5757B55H5p5l5._5Fl55ez5xT5Ѻv5H55s5>k 55㷇55p\57Q5h5D5 5㣂5!5a5*!5(b56v5+5L_585X5'N5^5FI5 &M5$5UK54Q5 4W4i4#5+5ˮ?5I5I5Ն 5" 51M5DG5LR5$,O5B5oB55i4r 5<%5A85w4S5BJ53p44W 5p+55)5N!5Lߥ5v5N5)D54|5;55145X4N52b5(5A25L4 4946D25zކ5zL5;Kj2/#58w4=L4]m4H35m"5)4+54Ź4~41b45a4S2543b 5W5Q$4څ5,@4494Be43x4VB4%'36Q3/*34y_2I44ʳ`2'4333S4B 84Q3 ~Ȳ}X2 5\־3T("+4=M^T?T´O&NH%1egw_HjH* ;7*Ñ o~9$}7Q{hi#7>nN"t"`3jG|]{7 =BFje3o^N2bQ@OHauo34y1M-Al4c+CQ ތ9z=L/~l ACsnqwxjm(n#X` &+L$mI7&y=?2I uf[´}/ sR+0*qA6; F z;( B&lH[I 9ZAKNl̇cj[ƴ;C$G4.06ҹ]G[S>)gV~qZD%ڕ"?}̴ 3#H j7PLϴ/]Lxe0&Pkp!!o%@X4N-袴u%&XM>Z8Yy2_ 3ʒW0nKꗴ2}ܳK4740O 3>-U%OkXw=4y@ܳQ2AQسZ;ɴRL3 돳pwT ivxXϳ^&JiyX4=4ߠYU3ǭMYxմszI 3մz +:F1m443InH374Hʳ3}4۠49Y844^x444R3284&ɗ3a3;y4zt 7^4;4&v344,:44=4_44nU5a;4kU4_4 3Q3f|y3]4F4{44f2gǠ4R4á4 4L4#5O4}43/y4j4`34o3"54D44F-4ᶮ4 4;5 5t4d145Γ43M6B4 3[54ڭ44M4j53F4\4-ئ4~&59h4h5i.5xɍ4T4x44-?5+4=944[ 4̀Y5Yz4"x44d4˝44l4n(4 44b4@.5>*5-4pk5X־4'5144'?48x4ƛ4R"5%5O'5 r5X424}O4™54:5055ܵ52b4xo4O5{p5h4D=54kW5`J4v4*5r5 45j4_m4 24@55 55=54z435μ4O4 84~Ƕ42_4F4c*3# 544yb 4m4S54+ 45pH545>45\494o5H 55T4$5nA5=4K5ya5 5%5;50"O5m4sO5;5h*5?554v4O4sI5[ 5o{5ť4P55A8575Qv4~5S5*55n;5!5#@5054+55U4,5|=(5>+5VV5*[5z54`I5Sh5.85"Z5!4(p54b2-5<4ı4R?5 %5Q5444d4"ʮ4J5I4545>5~4^15.5'5Kb?5A56f-5%544 5 m5_Q5N^&5b4a4*u4G65.5~+5Xb5954<5%55*{ 5~65%'5j>54N4c5ٖ5Q4Q4"_4ޙ44*4z44*'532f5843Ú464<5f4K ٬4044p543,54 5A'/5:3#23:24 m]u64j%4y4<94|D4P[s4p/<4 4?B4-r4x j4 5GG\44"';4n3M4 3e94z44,954401B3U4J I5<D44bu4# 5ȗ4O4\44J|44(;2H57X4׵3*4 Z4438~W-4F43Al2ҋ435 4" 4%64)4*4{544d3T[44V4s 4~r45f5=134k33544#V25)55S4Bҋ4n4(4GH402e44]l4q4%4/p42:4V4{4;?A5k4/b448H443oe3y4i44lx4f42444G5㍎44n5ˆ4 4444em4Ӈ 5ZB4I440I4Q4\>3,44ʊ2i5 454~.5X4'4k~e4y5y4L>4j1K2bs4] 4[4DY45C1ֺ4ZY4wI|4ϐE4*3a4`hw.o#'31=Z;[4og34<+38Aw3.>PW=? 3ȳ35捄Ye-AL2G/4304j'$43{u3ZS4F4Z*4۳3A4u|4 $6I.4J23j426+414ڕ2:&O㯴z3ڴ\R4ų%Lp\nNQCW14δ8񀴟G{UƴBZ3<DZxg4Fӳei3ZtDB6O?X#g1ȶK!r'0?2uϴjk I?/uU&E;*6$ tpQ\L稴'9 `dղPn¤oTs9+67ܴcŪVT.ıY#Jz7W"*=%i:Aw7l;ܴ5nU񑳹 δj ݴ~yߴz70 ,?|*1Ҵo4K2z}/:ΫKvܴFV.^ ?O;մ`~ᴍ洢Cz^C !ItWDϴ"0R:!Aôkl8"ƴD:]Lϴ Bд(?UѴOdgٴ[C%0rn´!ʳ ~|K ӴﴢT @鴸['2I.u긴#*˗ecR-\2&Me38gkCy؀zA1ڴ, 3.,`U!^q۴v7/x\r3Tb!T|ȴ >*84)³ub <3)8O3ܳ4j3"4 3h 4tVM¾:Ϋ32C4"4i4|X94k31Pu 3\jܴ3##4xBI{2^崝43sjnyS$ȳ9Gг)򆳦MDsJl&GѴ`1Ok}7⪴ִ1,?`cڴDV3Q< 4"lոi3i޴D/7Hr" #cߴ XɷۺFv, 3DUvAe״43847,UE]гƳ 32(4P=sw\ʳZ͇3 @ʴu"1g3r44xN4\r|4r=*(44p)4CyO0]}\W%5#ٴO͑ ڳ}5@TQK"곪ウ{3 l;B?*3ů+3v˴ kP8154a\L'?3kTvFL51 jP(<\r3px 3g?L]H2MZⳑ_ԴL3L1^Q0V4~3";:A]4Ӳ?ߦ~x3ُOy&L4Xf3߀4AJ 3o44yųW|T+3Ϗ1ײO4F39u to32d45I4=M-44K6’az^4:aj3 4~4}4 3I44*4 R4F34郴*3z,49 434pߗ4F_4y34LF2Z4If3y443!44]5̮W4@4Q4+g4)4Y@5eY5"554w}I4548B4a4N4_X4 m304p43?44q45{3HS4b;4~4H4xA3N4@4"4pij$4ލ4]4(N4]{4Κ4ry^%Q4Gm3i2G\e3C3nF4{ 4]4,:г|K4Pa ϳXj>3+a30Ų3$4024(q*Y+;Y~ n^cӪ3N@zBͅշ(ക[14%3VFhk4׳nvm쪲WQ18vnഭWvT1SY̳A 46Ue]*<2۴Fk7 'G4>"FԳ^h4?=xs43v34 -[ 6IS 1j44Fj3D34DJ\4$y3442鳨I(4سOZi3F4y 4K$4d34/442 3C44Y~N48` w4}|4{)4M4t4y<2d7W4'4/c4=3V]c`4ڡ4G:4L<4F4"?4.4 4xPt473z38l4؀3j\4W44>4MJɲ24ы4Âu4V34K4?3vu4S4R4AU3*t0-4t?2^4%5Wy3"3_j4;Q5 v4*473%SB4"444 4f4e4ά4/4׫44,vp7234c43Y4U4R4^1|4Ќ/ٴ4wtճ׸3a:4X44znG424C]:4iS|1u4B446rZ34sc3P<484ӝj34A4f{LN4#425O4-G4ЙM3>V>4p4\k44P31513N63+س(3A3l"3Y%3.!YW4K4؄o4v4G4p45ೱGW63s22t3r4u3x'G4|quX4;4X{47Z3B~3Q3'"E N44J NQLs4?kDg1i2v493-4{4Ad4-%>-m*3W[k#3~P{NO13T72j'54q4e \4-ݳ&4@4*kEĥ DZbNO343᜴5ӮA3 #"Z馴Գ䏴1ϴNqje4.V1V4Q6Y4:H3Zd3'22Qa4xX494f434wH3F"e4x3`y2mY4P4Ν4=`6N3 Z3޲SN(s4ɹ̹+4_􁹲ѕ 4` B4m25o3xLV.4ȳQ4?3lh%4zO4!o]Wt-2ʗh 1Q3,Wfо3=s3v´б3t|[1ჳ\ߟm+ٜTU٧Ҵqӳg*O f,S_ضŴ3dk  ˴zgOaz-ZqѴ#owFcFtT RJjB:,%Tȴ.yP}ī%bӑnW2(0QA3W3ܽK c ,5ON{3 Q4.3K۲7fb74S2;4q3!~3ЀX9{j+4Ph2MG4㲱$xJtX![ zgf2킕{V8 s]6WaݴjZ ѴFJT2̴^ƴx%pGTᓴD}.밴H8Zlj'x}Mk]ĉ¿´7Fڴ$ ^s=ش55Bs5i'0JxŴc\M0 Ԉ@1zJТ:7't%tun39dc*2C Jn`OOj;!\*Aȃ&M-B2(|'tf혋||2If>+8NQ9¾3YݚlbN@a5[.BBC?W L}ﴈ AcܓY g@%L@!>iTaukwKjSn jTN>{*UUKCjҀwGڬ$bN61{>#4-/&=3QP؀`~ C6ۉ$oNCA$Sb̴P!6 C}A;f xeضaM}<+ASלx x!NPJ`Vzցem+P |SV3-%N?b3A}hH}zhiZ&j.D!7}'DkQ r@c6 _Ӱj3$ڂŴ|5aru+ʴ\C`0cܡTNg8&3d̡4#EEhN&)Jڴcʘ /qL|z*Ǵ2IVc9-a2ϴմô ښO شg@ߴдk.޴!0T,]]/a⨴Ya = ̴qwT)hFɅǀ&L:kc'ȴV迴t`-=H_u3!m7*3}%3V3g3͋3I4|4tCMuk4v4K]'s@"4P4=E3.3ɏ_44t4.4w34z@4|4b44?*5@="_,4}4544K4Ծ4/5M4?5X4*485w5'5J4A35@,5A'57(5i5J5m45`5 5\44.3>5nU5qR5^55F05!5w05]l5Md5P5+~4G$5?5O355}3&4:5MT5k/5l/55:4c5j5Թ:5x5| 5Wg44KM5@"5c,44+ 5z5t`5*57D45 5[ڿ4 4-%55VL4t5$5&u#5h4U4;b5K#5F4c'5T55J 5m4k4P5lh 525 /B5'5nB5q)5$]M5v5 (m565<<5Q5T55P54u5S:5'@5m5nU5w5GR5e555G:5L5qw55K{5M5jB5[555ҋ5a555a"5b55`5{e55Mt5w5\5Tj5'o]55LwK5fn55ƅ5O5V5JN5v5z5`G5l5g5)v5D5 5ێ5m_5"5E5A5 K5RE585q5Ò55b 53b5ߥ5*.y5$5( 5w5p5q5fу5555oΣ5`5K55r,5z55+>55`5d5h5u5\05s52w55 5(U5d5=5W5ߦ555652w5p5:59S|5_55]5b55)k55!5%5>5oh585Q5|v5d<55̗5p555k}5 .5Tz5۴5[5d5o5$5dh55k5tL55X5w5O5ä52A5p_5q~5ǃ5l5݉5-5b5$5>5ާ}5Վ54/55U65`/E5K5iG5~qY595?U5[15G5[5#wQ555k4m5MK 5!4V5v}5d4/55~44S54}W&5&4d5f/4~4:5[3.24B#3O?4g 5ZMH44+4g42\4\5 4Z434Nk4ۛ40454سP޺4LN44;a43[uƳ2Kޣ۳U2C2Ĵo%Q´ 4ƹl?0 ѽDӐ}6(p cJ c FjдnJFմJW%4N AK 漺%`*>ƴoCqޘVĴH? 'Ӷ! O0.,yQe"NQD' 2ִ )'-AUzm۴%`~%!K( WFʴol Th:UG3k5"=6Zxli]o.EC~EwUX3k Q\R.`δgH9M.K񵦵^ |VV{N䁵r摵Tml>kqm g曵QfڕayمSкDi>h{d܇mxP`OVԒ1qը-ĵ˵te7G] |<Ƶs|3-Rg'ŵ=ʵൗ/ŵ֖&#۵3>{=3xQֵoA8۵rܵĵJ̵ֵk$|Quϵ#ʵ|,յRε¨eV޵-͵ΏpϵRȡ0¤ڵѵ3 ŵ\:ֵ$̸/ڵȵ}K2]ef)32.8p>xO{b$4`3bT0͌b:_ݏ~,ITR'lc]jIkRQ; uS2^>q9p 4x/fKxx-GFW[AC&#-`Stor"NW4g*:/*?AR.{/$n)״:ߋF O*n UA8Z6- DQ _K~wc*pd۴P.? OA`'ٴ;_=S6_P]Qt_sp{L4 Jnseʘ&MQ4933\ç4/Li 4T5mt4kJ4<14 34C4\03414=5/4$4ҹ'574wN42}5>4G$54i5 5#4tg54ْ5?.4-4eu5?4.5C 5a5Ԁ5 5T5D5@h5Y5)5?4+~c5&|@54R5lw54*D15(Y5"^D5/5h55ǕL54Nu55hd5u~p5wҧ5w5<35 5-#h5C\555m55=Q5`Ř5ft5XZ55ɨ5ӕ54|565@l5b58҉5tzU5x5M5,5T[5߭5n5G5"5s5L5EQ555p5^5,9555ô55`95΢505!5k%355t55N5355d 55=Y5&5Fۉ5-5H5 5S55A<585 ,52c585M5_55i5u<55Mb5P|5k+Y5k[5~ t5ud5Ì5%b5u5+n5};5d5ی5vA55h5-#5p5r5G5M|5A5_y4(5Ѓ5%J5`55=54I5Wm55W25ѮU50W5T5\5n5*95Re5F554x5?5555k55s~5I5B55kp55Jm5nz5"5 b55P5t5ن5K%4n5 5O{Y5l5 V5|Y45ʤ5kL5*5G5˨54_!5x5ŭ3I#5u> 4 345k=56j 5k(4 54?)5" 44s2540#4&4S4I4Xϳ"PxӳEd3U7n4^I[벨c3LWe2i X#34R*5ZZ ,,SU:2]#? 5NҴ|w3P9#ӠG4-zwu4 ɴ^`V 6NMރA TEz]bE0]\Xc֊! Py[3_բd2a䆵!8oZoqiB?B^|񸂵)"aa"ocΑa.5THt-x[ƴ #ǴYn,}OALAkٌ3RPoj6nGUaԴϙdm!bsHQLIk),fYM'"vP5BnxTJ4[X0hp6D= :r6RD50X%Krb݄[k0jy|t} *7NQT܊ZeôǤOvJ'uw=_wWͅ8Eߴ_躴D4촾y \_wx !1Ee4BR9ǬgvM xô{ m52o[C: ;P k-V'qt/yLs0$#%'S&`PY/^㴘3 ִ愴nR_4%(V:__įFR#{_ȴ&_l]g ٴN>a3wj;:!SʜkrAF$Ѵ):%A69:j-B(y³3={4w(X0*:iOԳ1¥33hr31A4R7,o#|`4J ~; 7m38&n4N'40HOko47 2D74Tm43ZY5x4 4å4Ƃ2d'4i|4 3>4|30լ4j4lp4JN3!'4 3zC3|X34244E3q3443e|445ٲ3490q-44k444 24O;-()443w4u44{3E}4F4"Hg3[d41HZ5[4x4444>4W4b+4t+5444Ģ4`5pV4h34j75HU45[<45W4Q5^554 5D55445-E4cZ5485D~5W4(5@4'TK5̦.5h4V 4pק4ۡ44&a5tY5i5l4w45T95Y˓4955\5h@4C4䪜4(5:55hΝ4(44_4B5cQ5L54B5W @5F5525a5+Y5Q,55ֱ4hvO5R5C45)5eE5lm5b4R$54|<535[`5PY5%I5Y5Q&5/5O5ǖ<5T8$5׵5ޛ5X5Uy5DQ5C35f5K5%=5*5i&5g4 I5L)5+ 55tS5&5j94Z4;5c5o5~I%5E445+5|451J54?_4ћ45૯4'5Tc55;44o45 5\4W44(4D5F45/554P4|I54y4"4n44HΙ4l45z4Z 5>E4X4ɀ4-54U3a454<54p5»4 5ɖ44Pc@5`94d4;)384}5R4Hk4 4<44^44y4 4 ~4h4k<4` 45tG52444d5p46(54z94=w4I64m#445 O534vD4r,4ɥ4[434|A44C7444*43\ 5Nl4c44 3Al3з4jг44ͽz4|3N34̑4@m4TK3%4442E34S 4{'44q4;3B3µ44TI244&3c4¹4y5՞42|4J4)3ʒA44F&3 3ׁ-4c4ce44I49N0RݴMڲXUY|3Ara2[^4߼٧ƴ#(g .,sBRY,8᳎鋴{T> Ѵ7yd"M,o}ɴM1Mô~a4l ۴@*W <ӴBRcش/ Mһ紶^^Hm^4TY %ɴ(4S,Yx״">Ŵ[ܴmc%B&&M.t4@Rؿ )oǴ 9UX#2O @9a%8"Gf=r?ݴMִ+e_ ڴ>6RQ5-^n`CQ7 ;2.9rlr{Ka?R:k[Vp f \MypRAiU'tŬl'P\0tUaU/Gеʵ n&yJhhm{ xCmMi͵TQ}|@&ҳ<9 8ŷg$95 +5'F5z5`5fd5o5~Մ5מ5ߨ5w q5e5_̊5z0558n55w5<5o5p=5׷55n5F505•5 55f55;^5a=535ˣ5<559D5)55A5)Y5J55ɺ55555S55#5555&5E95a5l5̪56]55?55B5 555Z5ċ5B!5 5۹5ܞ5K55a55Ӗ5-5Kf55[5מ5j6k5JY5?5;55:h5155X5O5`5w5h5b5q5555w555q5w5L5V5 5\5o5UK55J5?5A5`5=5K 55R55`5[W5ה5t5\A5LF5%55A5}k5l5Q5XF5ٴ55z955k5(5P5&5C5#5555I5)K5!q5O555[5>5*54ֲ5!5*055\5P555R5;u55555N55/5V5:5 5[5{5ƞ5>G5Mّ5?9`5P5s5L.5Po5=5 _(5jb_5q5O5R5^5W5Y5g525HZ5N!53$5CC5X54v4FR%55''5T5*5w4454xQ5 454PE;5544<Փ4]x4/544445444z553Ӎ4n4s55}u4/^M344G3Oz3B3#4Ÿ\4߳c3{4|44^2Ll2\o7"GߴT3 +mg4:3˴>L F 活}S wô4Zqt3Ԓʴw a=fwh:DlFѴh+%<ִN_OWc` jUJRD1oi픲⃵ƔF.V}ג/_Ea C^@Qy>ӵ ̵͈յTð񧵣yj=ʅ˸[Uٵ=+ߵnzǾtfϵ ᛵ_~ⵃ صy ׵[ ڬŵֵxõ䵙=굄;õ3ݵg"ֵݸ͒!d ͵V=ݵV<~a,Ƶ~ٵ鵛^LMUtϵ_굨ɵh=Gh'鵀|']ڵAFydiٵLɵص e﵊}HԵ޵pӣص͵oHb׵4ڵпy!ݵt൬|ܵ뵗ص赈N__ε6e [o:>?ĵmnT~o)eQ=CbA:aq璵is2}<`vQU{y7E{%!-F`/5qa;=:r: B]̕ $FZ@) .0YƴG.5 3y?⑴`/` r!' "xv,4XN:83R2/R&7ų/,Y33=/}δ4I2Ȏ3C=4|.3؋44e33[$4.3z#4&3"414fV3!Oڧ4uJ2 4FZ4v~2OI4R߳5Kj3r3h4o56G5144eˋ2F4yC5{4qE4!i4 e4244444w4 4"4# S4N44u*574h4s 5B4544"/5p5I\541'54i-5R!5~4F5=75\)5(5'55Y-S55/5ʈ3565E5KD5 55}465r=4tMe5? 55&5TO5OM54[;D5Z5w5O5V5,5Q5595ND5@5l 85q85L5f4P q5M584K50a5i;5d5E5;$5d5Ѐ5~ވ5y_55C5q5Kg555qn55hU55Ck5Z{55\|5t5_5Zl5i}55U515657>5<5פ5B5G5s 5)'5s5ND5Yt58>5A5g5|55E5%5_50L5`5J555z5<5K5#é5X5$B5ȏ5Ht5t&555)55)5'5R5e |5+5]5˸55d3p55dv5Pkh55䶕55N555R5=Z555LT5CZ5ၓ55@5S/54505 5}ޫ5I.5Q5&5Om5555[5^5gk535Nk5ZW5o5"d5/u55Ә_5#4Q5,c5r5\O5Kp5#5.G5x5Wm355575|(5+HE5EH85<5yA5515@5T@5485_5yZ5M9'5r55,p5GY5{P5!5y5a5B5^|5 5g5L5Ptn5(54,5@55h5U}5Qh5c55]5O54rS5-352+5 E5Z565 5!5[-5Be4:5$5ל44O4,?[5A5H 5&5pY4d55>654/S4)5P4E4#5\414$4Q4_44g 4RJx3>+5D44P"44:{1wk4b4^G4J24krP1A؏4'u47<43g)2G׌4Q4?4ݳ>4 9,2E3攇%2n 4FjJ5:4 7'3h4I04{~ó4Ŵ2l"u4{ڡ3=8\#|pڡyU3?rr0~״д[F:ʴ9h qAk Z `cDJ&l.*;=Ulxy-Cp_-cE͊HŴ raK_Z F״i-fL$'!ȴ݁ j3JbT3:6FczdzOmh Vj6$(Ŵ'p!^`l2=_ӬrK(-v2R3c7A.LeǴ&^ҾzJ഍,G 4=P2Ɗuƴ dqHxK 3?64ߴՊ34 3!(]oߦGrjߴA#i ,bP a2La˴>˴+֢˴3״eMKp3-f i״A`wQҏE6('ôEm9 ԴմGFZ]j> 2 崾#Շ[贲7O27#G(QA(ssD"J@-3~QLg2#>Tzft+AO4CX_BOa2,Mʒt}Z㬫{F44³"鳖HHo,B4?_;|13:k 4u~4 i2G43_H|óZY:5302n/݉]^.VcGٌ364RC;˲kX4"4*k4|4m?23-424D4T4ki4♾4VF3M+3lH4,35cL̈4՜e3c˳bT4t44E 4w~304L-43+434Ĺ41'454cm4U444JO41h4y 4ў3X4u5<454W4f 4T54uC4s={4>4J540X5P5t4@5 4~5c%5'5 43p.5Rx4W+4 d4|׼4=44 -4ɾ.5&o?4ӟ44a4/4W4541535a%N5YSb5|5LF5Ns5W5RK55f5/J5`?5}25u45nc55x5K5fd5.e5N{5Bj5\5c855) N5FT55;5St)5,7R5i53^5e5;5$5)5S5E5%5?4\.5kA5;!5`t5>\5U4T4o%44.44 4ļc5#5'5zr4@5J55 5开5 5W5M55 45)4]4K 5L64zL5TT5144ߊ4!5u 5ه4{5r54T3+4ʪ35B$4N5$4+5Ca54544!<524y14 5e3.Ȩ3S!5%55 5~44{94Y54] 5L !2K25H^4mu4D4v44i0h53H 534&4vDe5V4k04݆ 5ӛJ4ߌA4)4f3 4F4 z4344l34V4$4 K4b4c3Z>235=4؇4p2{4`4"cx4?Mu464M+5E4uIZ44r4*H1o4@54β+4_>5_5 4SWy\4I4 j4<93PT4<4"ICx+nj4< 4a)4>3cѱCɴ"|"P Oa3!e;dFףdzƹ 2v.h:e,1:X>M[w$U>g"건-*k=,(jiqRA^}!*0(}ִ\pHݴJD? y,(/SvW-3Bx(ꐵ$; 6ڴ6?'X !10ySGnGڴF|~(\ xgC1Rjڷ1}޴vYOYwSɴWD4H>ڴ Y"] 5=M]}DδS6ⴹ;JǴ Ǵ1{b7226G㴃; &:騳3/"˴@m m/?pnmʴtҴ,QʴִH4*aµ{ /I@24[ao״9A^/]>6ƴL15_짴jM=J-op8*We'a=3NA=^4uܴ#)Ҵ8'A6+شoh+痳I%ڡKrM=HNp%* [|HٴTHU]3$~ niZ o: a3srvb"紴]봣' ׮9cvB Q1N]_H"ҨP봖T3atN*aM,rSқ (W"54cc^P WD'e2ʹ< 2:g>"h%ԫ/MZa3 mnt1zrp)3+04Lm(Ѐ4em|&E3n $en<4Lȑz]1e<24Q4©/ 434d, g4c4ۥ &(Q4J4hM44D4o'4@4*-4/4R44!4N 5K46bޥ 5q474P;5fHUy4X乕48ŷ4/2 i3R4\J5k| vr3򽭴!2b4 H<61Z35QGq)/4O((A 4!3AA`Nr!N4Υ3%2t _Vq4V3}4-4v;瓴Zq3 Z4733+$\q>tKK3Ygٔ3x>3US4q3 63e4y4m4"rl<42 l/4Ζ343$Sc]B sf"Y373TY=34n=F#@4+0 a(4г qT ֓3ł64uA <43In{eL4;d4$״4 44l.Z2Z2oX4 LW33]3Ĵ4) 4v(<*x43uI4lT494_4 3rz3wŋ=؏3"r4ݶ?efR燀44 3s53-4z 44@4r4Ӷ4rca44"4 3ѕ44ް\444N4,54B44x4}4 4v4y4+47d4}4 4DIJ475U 5h46ci4' 5S4|4?4Ci5M,56eD5l434/r4;4 5 )4>>5=4m44j4sh4J4m4*48x4ϵ2 4{4l,b43<4^O4o03㴢m3~zPe4,؜364§(4m4SBht ,S3x3Ǭ44 ǣ3[B4a4P41y4>4eҰ44y4~4 <2?4eFT7C4P[!4/:4b43.=4rd4r+Îyz3Q{{348ġ383u3La>414nMr4#S 463342SZ4 q4Ǖ14s3#4hS4K {\ Wj22/94;34%,)3l4<ٲ3j4 4&![444(l4%U3 I3LYб~v4:4^gꈳ 4@!3&MKʴTY2' }34SkO2 3場 c.4Zд( 2S8w4'42P74R4]wgph2653)eP០3lf2ɲf4~ݴwǴ\̴7334|e枴QolaڱS3Y*e@p]Yh2y˳N =a^4"s3V3ZN]ڴuM۴2]hߴ+^G1\#)}2.(f"4cs8 x^_ Ҵz S !+ |y2ȴZ$uձH`:dͻȴ \K˴䴳+;Bڴ@1_Ys,^JڢZ`08O45/+ 8M%@s)RX^ݸu-1iB!<S#\ /fc)K674&b^?l 䃵]l-]lW5CBE7(}CcTyyJJ :j $0M&Gش~JI3KH2P403Wմg5T> iY)!~ ~/O*RK6Qe)=P" rsl33nEfz!'m U_rH": Qtô2̴l ^4F'2wI1.kƭPE/F_4#OH"'״(-i Z(u@(F"N_>*hN 3d\Mٴ1̰O2<3̴H!IzoD%Xy~촷1~'I<#y|2mh3gִRyƴ#O#5 !diʴ(sT213ʴGʹI@-1\1ьk'/FҴŴӴn3[Y2V/G4,L1qd07zxET3"*s#4u4M3n3j`#3Fpc4َ3P/uȓr4sEz4'3H33kB_4Z3=A4864`43b45u5d.5s4gC5.5Pc5o=05A;5IY5~>5^065ӊ5Y5575o5w515c5dKM54455~5r525JK5fNv56q55D5\5F5o=5]S5h5U5ew505b5<5E4Zh585z@5_B 5"4x45N75555B[(5r4k4M/55|C5 5B5.Z44<5(5|5[&5i4)4x&545Pi5'4NL@5y_55O"+55E5nF65m r5&5Ax5 5Od5&`15\Z54+\c5f55J.5ip5lg5s5v$5895[5`k5n<5}N54G5hZ<543[]5;B5w555c25b5Ct5=R5$5QD5+Fl5-)5Y4*J5`"5c$4 ߐ4%p5:95M595`54AOS3E$t3J3q/д-s_La 4ʱ3i14]lD޿}$$oƟ叴a+< 3nPL5ݴM ش]Ñ-z|hش'JŶgؿ3 aCfwiPLY 3: 3xNO>9aZZf)ʹӴ/v%hc\*虳(ɴj xw||n@@0$ڴ3w.%jѴӐUIC+XR!ò˴Gִ]fb.e܁ѴiY>K{. ? ״% E 10u-RĴMԴM?˴2ȴ0R6eRG(5|YjORTNYt!4IU*oY괄dش'<[cA+wZ0Y_@ež1sҴns_=H^CdtP42k3 4=O4 594233|39*"3Bdz$2U34+4m4_>T4Q3 x7ﳺ2g?ڴp2i4|neqP3p7ڡ+@󜳚3VQXd _3O4744 39w*3ZV4#˕}oYC^4IG\vq[$2R%4'x͕3ʹv9o[= ,ٴ -̋J*oߴ"hlMqǴ+)vO:cО|a дMp$яôS贫-\9۴~R hWvn)'Lk,\PM2@h [Ct c,9MRF]I`Ebʧ]n<gf3R 𦴡Iݴ).c)3L]NK K@036 |%xpemq̪̝ؾ3Qu(.gN3내iٖ9cʓ93) ɴaϴy̜-4? 4Cnܳ/:ݴ%Qg<2d #6̳pmAl4I3h44ʻ2l4A`d+;33LA4V3_4244 |4?V4GŇPc+24˗ہ4睏4J4K 4`%c4B93IFhY7 xb42l4]4%4tj4?Z2E&4( ơ4y4T342rG44@(046tm2M43\TU4vP 5<332_q3B4 474i4,2͓4=74=5"j44944g3_%4zM4d3?1}322:w4/:2$34,4Q g4f.5|444;+3 ;45[4y#4! 5BD5d{5C5n545N4C54ӧ4}4O5l4vK4Ă5aX44Jc4_5} 5v4D"556`4z$5:84585!=5 5%4 .5ɲl4y2Sq5555:44S4248 54o494?5446 4,53Ә05Ӗ44'/4+4A5t5W: 5p.5/5.4cg5RD4q5H4mZN5I54K4E)h42,5fH&5r$5.&B4Ʋ54r4.?4F^5;N5X5"޲4M54 %4p4L495|4SR5W3ܼW5ϴ4-55<4XC5)54444r `544W 5ij25Ϳ4{4l4B4%$*5j4hF4s4(4&5t 5&45444Ԇ4b5W443O4q546544"T4d4=5{4.Yy/5Ι4|5~5d5ò4и4555f5E 575( 5u5*5l+595qG4]w5%!54^L05x:5<4Xs4554&54+5e>!59f4Z5kL4z'5S45Q:5J5/ 2-4V6S^iߑ˳Ŝ `sOִ&n3op16*J.۩?'@pD֋(6@pNN͔{[]yo+ ӗƌ4ٴl<7Gô\3rϏ=nϴOറt?EX7ݴ> l㴹=u´8?VJe8?1qE$cgx(y c*I񴿵2;,%e H;8 ,akôĆ.2Vʳw:)/3F3l.1Po3˟4En+<0b4#3$%',4Ϳ 4qh:,س50-gidƤ3ooɗ4&FfDJ+25ύ| vN:44304JR+33\ttt44XY3s*4N3„t1Gk`2$[Ҵ\?6vL1NB@"4ҨPWTFb0\Dn23ڲv\MD1GbwZ?3Kzݳ C8T4(rEP=?v܁M̲7pG ״* -ܛ2Z-26A4܀dҭմΑAl25 ($ē˴{?saɞU˴ٮ ` \KP3Y\c9sЍa*J <'0y'4P0CZ^SW m;SִAOl>V&f:Q+Bsj330I ߮/Y^T0EPVaBϴ%/"߼o=!+κy7  ԕ\1dL0$ߣ>Zeس u|Xu2o`ʹ取~o𴏨V2+4уҴoִ44U`m&cxNb\tʴ88˴@wS>w0H "ZuS,:贉SdNkcE-",*3*8iTVRW *˴N(d@PPW> R{ ִYTQƀ(`W/:+#{Ju|L4*45ns4(V4XrB5544$$54B.4^955S5n255r5!59w58553i5O%5 5 O5 "5[f5L4 4445z5h4y5[5Q4\955f4` 5k:444 4y!5s?5U5454'_445aO#564ƀ4q:54f4A4M%42054l35M4 *4i 544գ4344r 5l44{i4u?5ɾ4a4;J4dի4J3cO4d4244Q644J9$?4FV4ҿ4O4X&d404 Ӝ3F\48>4N43 4W;4x4L~44a3G434Ѻ52œh4pb3{l=4@WI2f4=0424+mN4e4l50WG-3EU4U4vLP 3{4Ʊ4L:4֒4-4;2τ48 #/4..=!Y40ij\o4;34Y1ʘ3C4.!Ѧٹ8;)1Q}2Sw@4+z4ik4q4H3A4"2/24o4Cɲf3 N%35&4ʩHquS|+/bk4M%d4O+V<泴4B)5c=c3k.a;ѳop45Z3U32؇4O2V˳S3(bóInڳd .4D343:-V32ZH3kKg3<ϴ=:,g 6v? 5$)@񳝹P>@Ѵ1;fx/Zٲ4jλcʴ$ sǖBQ4!0G 3:nb$wK37[ՀUFa!9Jrab z/La_kڳ|[Jϲgs3|_sh4G23릴C(jI2Ԟ4,c$2 ƴ͜Jq%VCj ~V޴(P۴;<4r$ٴT8'CV N6F %4-. \紶|~*>ߴк-쳊 Miʜ`A3=`L޳3(ƴK]3 4 NӴJXޚa/G´Ȭxw3e*V9=؊$%rI":A/ֳHXǴ%31г_a32;6K س*@LL2gz;*P{Aߴ4!eҍJ'M S8rukU̩˴fAY9ᴴ$NݴC^f6⁴x?SxĪ3hN*;平`.(UdVf(ˌ%33-/lD)BH[4'3&24W7H 2)6sˬز]zO4IHGC4ɪQ6hI̳T~43GT2lSg)3K73Gd2M6 3WE4*3}n2mȀ?0${S؉ 4>k4UN3;,94"3 L=39!4 34xji_S_>(xh52pȴ<4?U3!Ŵ3q@ 3V%R 4l4nt#4J4!2F4cd,323Z2q4S4~3/Z34}fME44R4|4/3V043K444{4vdX4<ƿ3B4|5544DG44014,4(A43)̃42Ƙ4qk44+n4S4Ǖ5YU4:#d4\54R44Jj5H4N 5g4454tQ44d4.445 4U5?4)2ng3Yކ&c44-2,,I3T4/'#4t4H4Y0#4DS #0Y4߶9ƣ3"3ҳгPO33ˏ2`h o_|2򾰴| l8b{403he$HnOʲӟz0쳘K#Um4ִs,21Zeo˴Uk%4I&Ҧ\cɚڳ/ "kȴ4ZLMߴeJPǴj@[xYqp2Ҋ&b,:`0զgwU ݴ,@ϏehN!ҳ?˴eI?}VⴳwH峽+EAqhp̴^R31ȴ]~O(4pb߮:ǴLVn~ 6֑/KDY" l"FZ3DF4'T32 25L+ij/3ҕĸ3ݴ?3 mP2A323ty3ςl#3[ѴX\Fi!M`SZežR53|)4P3/]1t^OEʇ3ӳ34>"1{9@ำ ͲE˳3ꑴ\1R3#<u]3Ae2;}ѧsNl0 n.YUҴ祴7h3" (K)()n -s Q2kDę!۵WѴKJdFִ4 %Ι3_!^B6BfҴIS(IDشuY Jq^M1DZApݴD$ 97᮸EnL㴼b뇼풙e㴱@ ´܄ԣ*ȴte)g\($_?f*33ζ@]E'&ݴB3by7*>4m~5L9贤q25G46˳XͳG3:cP42㢴ʜHj?ŲpF 2l[x2b^#ʹ:3#40~'ݳ Ӳm3 4@j3K55ƴDǴ]3"41 1[3: y꙳D6kw$G %_ 3>Yp/4x34 S@38G43y4543@4MC4J㲳~43T44J454y 5R554Q74>3Ru45 35W4b63=$34-5'%4O5T[4x$5|4454N45(4Թ4L3o4a45LT4)4"G5F4g4vg4%5|`5%444P 54g44^5"4]4}44,5d4gj5>5W55L95F4{ 5:5v5 545-5D5p5,5]95.4745i5f5=IH5:/565l55L 5 5Q55(5qN5nN595M@5\5L855ZS)5-F5f5*5QH5H55 I5ˀ5gT5|\{5H:5l,?5dk85|\5\O5h5PZ51(5fw5=5 55[p5׆t5s5Ĕ5;5~t}5`5X55wI5~È5(5f5 5nd5}̀5t5m5xn5@5)5&[5-@W5,=5qq55eW55ro5}&5vF5}w55}75ˑ5od55^55Ԯ5KoE55ap,5ވq5W5X05N65s5aA5hk5C5/157%5~5P5L45Ł5b5D5K4J5L4&5 5@>4w05"415`4n 5;4*5B!,51n4w4&+5ɖ4iX4-4o4g5T4Ia4Hc44O465#5;>55n44\5pb4%~ 5L 5DZ4345F4 }35m*5d !54qN55N5 4 >4S4-qZ45[55C3M? 򪳚#"4h4D4LL3K4y674'f!4w4vP43}4l3OZb4oo3[~2NZ4# 3 84Ǥ44R,4+}ә4i4#4l}4E*43xK~Zf+4$ڳq3@Pp.3V1ETܳ eʋ|t>ϴ7Ul5Ţ4%4?;3 \4Ai3>SCZ S3u`34!,u4H3d4U_4x;4ܳ 5~3|AOo ?603$7343=}WX3mO33-^3 }Z}la44 mp30dz*/4x]4δ!] DT69[43fFβ `3=*33 Ry4|~/Kd3z3`2֜44߲I284_2l {.VPɝ-99~sȳ%Zo.9Pjڥ3꺅<7pm2W3sC}e4ˊ2s_1>|4oznϨ`3S3 1Dz4!/0374ĪŐ3 Baqó잯E3c2=S 3(<FB!43?x3^[3h1LH83Jz44lO!3fvj>3S9M213Q3eAC44vX?42e8"44?a2c4445+Wk4Ͳd4~ٓ424E48l3 f364҆3P#4+3@X3π4hw 54;4Z44(54Dۜ43F4}4'5q*Ϡ14"4o$4>4E84]_X4s4Ƣ4X"V1tb3)4zG4W594i~44E4 3B4N4(44844M44|C44₉4^3B4A4L4;z$3C4854*4ED34gf4@4 73:4t4 3Z3bRJ<γ3fa+P3Gb6:4:T43/34cu44WH3z4bΜ35S4ZEk3}43!Ⲝ7Wj4)Q(C44^p2Fl4'XwJwz4 F%E3*}<23?j6'Qд13dzk4@ j}3h3Y2;^3i- Q3?V3.34d\ 4f4ҧ{4846<DZ( JS)]aYγf ˰wh3+ +\nϳg$4S2C. )3=RAj3b><;s/3HzԲ ΢]b1賑|I\߳m} |2ue3RI73ܹ3>ôѴDj"5y4@FѴHp4!"ḳǴܩôI3(|9}Q) |4Ǵ㈴XV H+ 듳˂2yX#3VҴg7H5дASԴ0-Y nHʲLᴹwȴ䵘 ۴ "Ayⴝ0K*wWTBܳZʴ,%>diDƴ 8"$ߴM@oc˴w95޴zE4'4r"~Z+9#Uq2`д[@">#A~5洏9ߴ*uڴΏ𴲇3CV}@d5`ݴ}a/ѱ8b*U?tuŴ{ô.ߴJԴjFHĴhkI)ͦ~s 4)˾Af.˴&9شe+ []_wĺ{,X,!T TT8X3մX1].{3[3߮ʞ >/ٖ7yܴ''щ3n O 5xga~4l.24&4h44Y |444k4Ib4333@5p4Gʳ@44S4\"5̦3Mz4#^42YZ4ͳ軳iUTfL03Jl3kͱ44Bh(@^~2f33"f2r,ֲ*l&34jl49&I#4K3Vc\]4vvʴ54Yw4B[4l4ʝF3m4M4W:4NѳH0~4w244N4e4 T A42S2&3.d]dևZO3S23='x2?32bO412{L4g53_2!33P`3^L_AԳ{1o5gT-"4Aq"KѳMN4{!J2F3i n7̆h~?咲 a W  22ɴwO>|oq{2NnSm gAP{ _5oV/1b2´|Z4"ⴥ0mFs&Y,G+9ȴt?J=69GU'N4XN5,w If>@Tp}u3K ^yDGjs`~*U]%T-adAU "ztDceN(H'j! > BXJwﴌ|t P\|MA@NĴ?Wܴ´)ىŴ fm=Z8'!DU鲴C'@ ִKm UyjVOsų@㖴6 oQuwM/Pn`Ѵ뵴?/IDf1W+Ms,ٳ\{GL$\b+Ŵfg.N|[t54ɽy2۲Vd2x vZx}Ft˳\3o":DIa(74_&Ժ3F$3u+A'HdƞSԴLw+3L봈nmO 4ANp峜0qBԏ]G2$w+ǴAδtߴyr-x82|1446+ 6]*@lB1GbB㤧H4r53gLJtƴ-L,R{[s*E.IG|o4g3q|4,;4،e4k:ݹ34E3:44L4g44ݽ4]%4g3W03{4Cx4ȧ44*4γX434(4e:4$444J33T%43AB44j)4;W54;d5\4a@4944]4t%5/455z4"v44n5j4,p4f?444O4,4+4Z>54/5\55<44 ӗ4P 5Q]44j4+A4e4cҳ2:ϣ3w<4p3`E2KBb4>u4)H34+}`곸߲҇"v3Q4K` 43س r3ΓO_+442793Y߷2#3}}3 Ƀ|U3E.4 "`Yv33DѳƙഩҴTn4 &մ2 3A4w.223׳ÁA3!462AgY3!4a493Ԃ4$43Ii4oz3!3 5BXe2V4b4(1q4ŲP2W|4 3s 5vgY;I33g5 +A4&q4!4ԧ44Si-3 6! +3SXıq4ռ4>go@]*4N434γݾkQ3$:4:Գe 34b4Q"4;L4eR4ڰ422xӲ43Q)3R 4Hl2 !܈(GIOq@3m\^! 4{[4Kv|h4F5wY3w@E(3'?23aZ3Y3]ݓk?3wt2}2[~sჳP^ ϳ[GE5I1?3̥3to|)6/N3A%s?TݴUȶ1j*b-O~GK5Z"ܣh|).6[W4i7#h^ d$ɡ㴡؊x8ڴ Դ 34xvKah448U3m4(d4",I r4I 2U14@ 4u4B4Ռ4N'43c4_^4:?4>4a3\Xk1t45& 4.4к3#:BZ44w544$5l+5VE5Y5I4Et5 5I4dM5N4:5yh55)!5,o5om5?5p5CH5G#5dK5,75..5Q^5E5C5{5N;5O4.mV5.K45 5d5D5%55Q}X5՛_5c5GJ55g^525/!5J5-5(->5F4T56i554@<5 +5ue54&.5Z525y]5#N4h25kaI5514=54qv425M4555I4e4 p5E4Ӻ4,4ռ54>54:Y45Q4z3n \4Z94Q4M]><5@4 54g4X"4e94}3?P434fv#5t4=4V4u4Q[94 44 54ڽ4`3B4 54V4>55_4i435M5Տ4>L44-I>5K54)4C24C 5ro444 4=4L344س35J4rB44?5ß444V44s4!4: 543&4T(44$43TI44^4Э4$I444V4Ӓ4 b5k4/ۧ34D944[4*w5(4 455[5955z5345q44i4F454$4쎋4)454_4]465{44;4)R(41&4By44a&=5|ܲ8=4MKƎ4pX4I4rڊ443~j44m#k4,Q2 43yu̳r:\4Pm0414&3u2X8kA72p3 q3O?2H*N!4B%:K3 ñ20#в#^%34ITU3R s:LX23э|a=3u2}}0)x#b92=`ȲQ ʙ3=2Acվ2`n27*!P4Vydz}C;faNDYgKQO*qrѳggs寴@@3BiB6B޴9dbwT?dP\>d:(2k#Аzs|ȼʫ5' 57QΖZߪup4/ҴʞǐYմW`FѨç%pI?̴5ǴIP S~HRfb״?;´ZI  i+p\HaI]ɳgPKIBѳlдr OlX;״7ʪGV*G2 rvnH6ߓ6q봺直)E![K2g ʴVo+@Gഖ)Ж@״bpԴ-$@̇-"_U0R Q5\_ vjAAAvϴEG΍lr2rjjU1 Nx1;Og1P?j h@OC݅K;ssh5^!=nݴp;<VU8^4MZ7I&.6>4O *6RG޴>ܴ>uȂ+>Ĵy5 ;U~JVϴ_#~ix8>ʹ"'O9}8 %Aʹ.kYv̴OUt+wT %'{Moy DXIDbV2\UZ>2IV #ʴђ.ƴ`l!"ݰ&ߴn*4⇴ O Wﴫ~ʹ4%ʹ"H&CpB76δ 2ͱ&iYKy洟K3hb\cώ3BG. ,n1@O[Ҵ*ѳ$3$ó 誴j>x&qm6F4=G޲qkBYljm N>b\|@F3ӴW 33-ʴn]R[Gto4,]He d,-N+4M'򔕴qjɰݍj.3^w`K/33w|$Pಟt2y*4^4y4w ٵ4Pw4\3m3%2 dQUj939#4|<|3p4l44h$4:?3u%3fg4d343ك'44NZ4IL44w4#4D4S'3EԊ4+45 585m4$ !45p54TF5464-35-5U45)5U4w585$5_G4?43Bb42 5r!5 v4Su4X5@47XT4ܹ45ڡ4H5E5 55 5>F5@B5L4W44]4uU?55j4@S15&*55+44*I55L41K5Pc4*Ŀ4245(54iu4/5Vc5]@544s?5g5}(5;=5Ӷ44a5`X5T85$5%5o5%5;l5<5)P5> 5]C5<#544ӊ05!*5 Q5h8C5{&5C]5v55 - 5 mo5CN55-5`4vh5,e5a55o5~5YR5#5sqH5p5_535C55h5i55[5**56a5W9>56<5T5w 5!K_5Q65#4w^54D5GT4\5]q5i5ɡd5x5e5!5ol45495 544X 5$XF544&5S5465n4m5u5` 534m1r4V59554 /5J5Բ4M545``4{7595 4cO45/54"mA5aQl5y55+5,5ț45(5$5F@5U5ЙK5-Y55KWX50h5155sPm5S_5;K54a*5`;5G5#/,5 .5a[5B;5RL550E5m52 55547 5y4*54`4,5̈5f50o4: 57c?575T4<5SV54U 5@ L53vj4WV5 4Q1525i"44uE5H}65]b5=75K54l4y4V#545UE5y35;]5Qk5#|5V45,g54\x5΢5V'44(Y57 ?5RD5rfB5F54R4)0?5{5|%54$+5A4D)5i݂5D5/5mpp5$54j5d5G5{54rsb5l?5 =55dL5E@5-5z25/Z4 5D5L55>Xh5R<5."5x=5O74 4G55R5hk5Sr4J5 4(5s45)5@464!e4g15r}4434t' 5vc55W544545=4*Q&1@143*3r4/#4l4~X444 4 :TS32R\BB{4κd44R3ߣ2/x4^3P2>dJp2O 혴GW+&ho44#*3w41 t&l~Gd ]`m4 4 m_e43*s. 3gx4P4V2=4,n4k2"3;44ӡ}Jsf4 2-90a3O.2[vy+qa2kS-& δvZ/m@;?&pRΘ3C7q9JYqC+[0Å5B "ﴪE=8zc^j%ؤ L9;-w- ~W8H?5 ^C봈n!,70!f D-]34؜nCcvXV62'8鳖2^S /2h"uE梴D`,/ @GĴa𿴍MTͯdp6Tn@F4٩3ﴷܺ' %j`ֳ|/=|"6[U˕I'dp5I-H2b ۵Ӵ\Cf!SW9"*}_Um |nRa]ִq }9q>?{s33FjwR*ӴH(C7wP`P.+&?*ٴ洽;D( 3V}4 jMC8Q@:t3Gp}i%ZA~+5lb,=Vz0Ҵ,p Sܴoִ@@c۴X.~TwO#׻(Ҵ,rU ~E29F| AYDGŴvI$\-xڴ.nI cUh?^ƴ!6ִJK6״!\!ޟ'Ĵ0 C5GHմЭQix.MQ^۴H1ߊѴ3b:!ΝT z(h=%z!,գk Jk&%'Ĭ1'V4 L˻:Z-2k3'-ݴBٴᒚS\ƱA*#4ڢVF4;ʹeMmԴb2$~-tn3x<}M/vg4oQᵴa3Y:r@<4.4y崹N4r:#aYn̲_3);I?@21&4l&4`3d3WM짳:4%@4d. 2!q3N34PRM4w3g3d4O6>M3$4lGBEz4fJ3.g1y3ڥ4,4֥44z4!4^55E2{f4?4 ]4s 5Բ4:)4!54ԉ4295g4)55t4hh4ø4Ev544B$55(515|L4 :4-54H4|<5ݱ5+75]J5Hc)5ϟ4t95lH>5\4Z54~485^4p;4{5?5435G4:5o54?5x]4ۛ464r,554}(5jO\54,4+5.A45i4p5u&4d4j44RV5x4<4Iv44s5]4Cݤ45!5Ʋ4<75s44/5.`4q4445G5u44u*%5i53w5+56 5`5 5M"51x4W4J5?*5 5۰=5o1525}EF5F54@U5gA5B5@;5u5.5j4I5K5dK5o205r4l57'55z5 5)58,5 F5z5%5?u5BP5kL5"65o5&n55,u5>5G55i5+5U54Y5G554n+5nEH5^5e%5*455N5>5}3558 5_5!5qA5!N5!5m?5"S55J-5 c5n>5.58G55ԉj44 5UJ4 55l+5`{5 855L:5SP5I5Ƿ4z 5<5"5E 51'5#4v4OrV5j%5A5w4j'5g5nk5LZ5j5;+S5 95m5 15F5#;53 54`5G,4F4|J55Ɓ555;4~A4n55*5465k%425r}&5N4{4 54B4r5 548Џ4b445fd434Ν4|45<̭4RS43^5 544S5 5 I5S44b5v4{%55 *4܃4z4*5`4c 5h4r5a84Q4d4845Tu4c:44Q4±'43K4`4>4j4ɪ4MjG44>Y3 23 4$4XL?4wB4 41ᬗL4bQ4n8ڦ4u_434^3J<144P.:"n4og4.3s D4 33KX4Yڳߘ3)4^u3d#[wv4:4*XjO4`@46|_4:}4#945 4;ϕÐ^>'k#cR8y)33Ǵ+t[KF8Qy$Jڞ@ `b(+[7KB-ADԏIugԴ3_U}ٴѴ-kQ3 S(δpYw%35Ӏ;>x'=䛴 ~aԴ:󴹛I*B <}紾}=`Ǵ7Fr 8,3.Ѵ򴝔0ӴK/A)õ Aֳ"=w,1 ´Ѵ୳0gbwMm]rDCQֹtCcS31д'2:R۴pj@iܴXt BቴŴǐCrIC"6:!ô% cԦa#@uOiT q=![;R// -.% "|הּh : I%+ .@S&_W0*X ^/!?μ[#F(- B.EqJ´!@ՄOboqtwJ=#-G(˴1*贡}0 OD .Qr¸=8忴fkJ"}>:{A`,vj,Z\F~B̴-3"1̦ #I?Ay&d')e|ܴ;-e-A0%+:!޴ `e5$6:2<*1 -,sV8-XZ=Уn:6; 2´ۋ"y`lahDѴ߳ݖGS`wںͷ3T34F&F@̴,cSp\y˞8páҴ瞴(14--3QW_9J(XedC2]%2ɴSy26`3h.٪dڽڼR%3|K@3ưyoǴx22ƚ4r}4&4نP4Q 3[4|VW3)k3=4}CL|44G;!\4go zX4o[D3<}3L443]4W 4z4skŕŴji244~2\ix2qƒ@(4/7̳#&/UL@4}[aG4`(!jc_iV!.ʹJ* e3I!o2Eֳu83ʉE4^X/ *9˴eU鞴:R-4_Hbk*KY1g躲3]/Y2XQ8$,r438S33B4)ѹHKZ8yZFsr [u"%aN0 U(){@oc$K*0Z/ kQ[Fzp|j[2T3=´?bʹFڰeB;OvΤ1`c`I,oQg'zژ~ZE5 QU<ִ$w2A4 4j48A 4_3[t3 3674A>ø"3I54@35G34j 4A(4Ө4{3uIO4d=1594 :4.V4LU5BhJ3@$4r(4ae3N]4 x4A44 ,3%r4s44u4[40'3~48Z4HN3ʞs4נ4vo44P5,4SܳN4Т44}4$5[4t4f4r34kD52e4*3-4>k5_!4XM4c4ˎ0O/4ˮ45K3c2g4u444 3<4Ε454rI44d44%T4#x4n=4=T4O4J 3i4*4n4jr4"4"44XXH4u^44Ɋ34g 4-4Ϋ4;/5 4I4;P4ߟK14x3¹4`4P4:4454S4L4'p;444M`4755 5-5a4ݬ4D&545Ҕ4x564'4-544m44k44h4O4X4Vty4163)5D4׷4k 4|4V4cn53 64N4;404j+4;5Ŏ444-5 4544(4*O422jz444Y3l'44Ye44H4x 5b4:425444drc-3.2.2/sample/minimal-44.1.drc0000644000076400001450000001054211751752333015247 0ustar denisitadm# Minimal correction settings # Minimal prefiltering windows (250 ms at 20 Hz, 50.0 ms at 100 Hz, 5.00 ms at 1 kHz, 0.25 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 22 MPLowerWindow = 22050 # 250 ms MPUpperWindow = 22 # 0.25 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 22050 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 22 EPLowerWindow = 918 # 10.4 ms EPUpperWindow = 22 # 0.25 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 918 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 459 ISPEUpperWindow = 344 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 22 RTLowerWindow = 22050 # 250 ms RTUpperWindow = 22 # 0.25 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 22050 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 459 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/sample/pa-44.1.txt0000644000076400001450000000012111320622136014245 0ustar denisitadm0 -30.0 10 -10.0 20 0.00 22.4 0.00 18000 0.00 20000 0.00 21000 -3.00 22050 -30.0 drc-3.2.2/sample/normal-44.1.drc0000644000076400001450000001053411751752334015113 0ustar denisitadm# Normal correction settings # Normal prefiltering windows (500 ms at 20 Hz, 100 ms at 100 Hz, 10 ms at 1 kHz, 0.50 ms at 20 kHz) # Normal peak limiting (6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Normal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Normal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 44 MPLowerWindow = 44100 # 500 ms MPUpperWindow = 44 # 0.5 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 44100 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 44 EPLowerWindow = 1836 # 20.8 ms EPUpperWindow = 44 # 0.5 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1836 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 918 ISPEUpperWindow = 688 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 44 RTLowerWindow = 44100 # 500 ms RTUpperWindow = 44 # 0.5 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 44100 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 918 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/sample/extreme-44.1.drc0000644000076400001450000001054611751752333015276 0ustar denisitadm# Extreme correction settings # Huge prefiltering windows (740 ms at 20 Hz, 147 ms at 100 Hz, 14.5 ms at 1 kHz, 0.74 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 64 MPLowerWindow = 65536 # 740 ms MPUpperWindow = 64 # 0.74 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 65536 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 64 EPLowerWindow = 2730 # 31.0 ms EPUpperWindow = 64 # 0.74 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 2730 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 1365 ISPEUpperWindow = 1024 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 64 RTLowerWindow = 65536 # 740 ms RTUpperWindow = 64 # 0.74 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 65536 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 1365 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/sample/insane-44.1.drc0000644000076400001450000001065311751752334015102 0ustar denisitadm# Insane correction settings # Used only to show the effect of correction artifacts # Excessive prefiltering windows (1486 ms at 20 Hz, 295 ms at 100 Hz, 29.5 at 1 kHz, 1.50 ms at 20 kHz) # Normal peak limiting (+6.02 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Minimal pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Minimal ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 132 MPLowerWindow = 131072 # 1486 ms MPUpperWindow = 132 # 1.50 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 131072 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 132 EPLowerWindow = 5460 # 61.9 ms EPUpperWindow = 132 # 1.50 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 5460 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 2730 ISPEUpperWindow = 2048 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 2.0 # +6.02 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 132 RTLowerWindow = 131072 # 1486 ms RTUpperWindow = 132 # 1.50 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 131072 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 2730 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/sample/soft-44.1.drc0000644000076400001450000001053711751752333014600 0ustar denisitadm# Soft correction settings # Short prefiltering windows (370 ms at 20 Hz, 74.0 ms at 100 Hz, 7.38 ms at 1 kHz, 0.36 ms at 20 kHz) # Strong peak limiting (5.11 dB Max) # Minimum phase excess phase allpass recovering to reduce pre-echo # Strong pre-echo truncation # Minimum phase postfiltering to reduce I/O latency # Strong ringing truncation # Base file directory # BCBaseDir = /usr/share/drc/ # BC = Base Configuration BCInFile = rs.pcm BCSampleRate = 44100 BCInFileType = F BCImpulseCenterMode = A BCImpulseCenter = 0 BCInitWindow = 131072 BCPreWindowLen = 1024 BCPreWindowGap = 768 BCNormFactor = 0.0 BCNormType = E # MC = Mic compensation stage MCFilterType = N MCInterpolationType = H MCMultExponent = 3 MCFilterLen = 65535 MCNumPoints = 0 MCPointsFile = wm-61a.txt MCMagType = D # MCFilterFile = rmcf.pcm MCFilterFileType = F MCOutWindow = 0 MCNormFactor = 0.0 MCNormType = E # MCOutFile = rmc.pcm MCOutFileType = F # Base configuration dip limiting stage BCDLType = L BCDLMinGain = 1e-6 # -120.0 dB Min, just to prevent overflow/underflow problems BCDLStartFreq = 20 BCDLEndFreq = 20000 BCDLStart = 0.75 BCDLMultExponent = 3 # HD = Homomorphic Deconvolution HDMultExponent = 4 HDMPNormFactor = 1.0 HDMPNormType = E # HDMPOutFile = rmp.pcm HDMPOutFileType = F HDEPNormFactor = 1.0 HDEPNormType = E # HDEPOutFile = rep.pcm HDEPOutFileType = F # MP = Minimum phase frequency dependent windowing MPPrefilterType = s MPPrefilterFctn = B MPWindowGap = 32 MPLowerWindow = 32768 # 370 ms MPUpperWindow = 32 # 0.36 ms MPStartFreq = 20 MPEndFreq = 20000 MPFilterLen = 65536 MPFSharpness = 0.25 MPBandSplit = 3 MPWindowExponent = 1.0 MPHDRecover = Y MPEPPreserve = Y MPHDMultExponent = 3 MPPFFinalWindow = 32768 MPPFNormFactor = 0.0 MPPFNormType = E # MPPFOutFile = rmppf.pcm MPPFOutFileType = F # DL = Dip limiting stage DLType = M DLMinGain = 0.01 # -40.0 dB Min DLStartFreq = 20 DLEndFreq = 20000 DLStart = 0.75 DLMultExponent = 3 # EP = Excess phase frequency dependent windowing EPPrefilterType = s EPPrefilterFctn = B EPWindowGap = 32 EPLowerWindow = 1366 # 15.5 ms EPUpperWindow = 32 # 0.36 ms EPStartFreq = 20 EPEndFreq = 20000 EPFilterLen = 65536 EPFSharpness = 0.25 EPBandSplit = 3 EPWindowExponent = 1.0 EPPFFlatGain = 1.0 EPPFOGainFactor = 0.0 EPPFFlatType = M EPPFFGMultExponent = 3 EPPFFinalWindow = 1366 EPPFNormFactor = 0.0 EPPFNormType = E # EPPFOutFile = reppf.pcm EPPFOutFileType = F # PC = Prefiltering completion stage PCOutWindow = 0 PCNormFactor = 0.0 PCNormType = E # PCOutFile = rpc.pcm PCOutFileType = F # IS = Inversion stage ISType = T ISPETType = f ISPrefilterFctn = B ISPELowerWindow = 683 ISPEUpperWindow = 512 ISPEStartFreq = 20 ISPEEndFreq = 20000 ISPEFilterLen = 8192 ISPEFSharpness = 0.50 ISPEBandSplit = 3 ISPEWindowExponent = 1.0 ISPEOGainFactor = 0.0 ISSMPMultExponent = 4 ISOutWindow = 0 ISNormFactor = 0.0 ISNormType = E # ISOutFile = ris.pcm ISOutFileType = F # PT = Psychoacoustic target stage PTType = M PTReferenceWindow = 26460 # 300 ms PTDLType = M PTDLMinGain = 0.1 # -20.0 dB Min PTDLStartFreq = 20 PTDLEndFreq = 20000 PTDLStart = 0.75 PTDLMultExponent = 3 PTBandWidth = -2 PTPeakDetectionStrength = 15 PTMultExponent = 0 PTFilterLen = 65536 # PTFilterFile = rptf.pcm PTFilterFileType = F PTNormFactor = 0.0 PTNormType = E # PTOutFile = rpt.pcm PTOutFileType = F PTOutWindow = 0 # PL = Peak limiting stage PLType = W PLMaxGain = 1.8 # +5.11 dB Max PLStart = 0.75 PLStartFreq = 100 PLEndFreq = 10000 PLMultExponent = 3 PLOutWindow = 0 PLNormFactor = 0.0 PLNormType = E # PLOutFile = rpl.pcm PLOutFileType = F # RT = Ringing truncation stage RTType = s RTPrefilterFctn = B RTWindowGap = 32 RTLowerWindow = 32768 # 370 ms RTUpperWindow = 32 # 0.36 ms RTStartFreq = 20 RTEndFreq = 20000 RTFilterLen = 65536 RTFSharpness = 0.25 RTBandSplit = 3 RTWindowExponent = 1.0 RTOutWindow = 32768 RTNormFactor = 0.0 RTNormType = E # RTOutFile = rrt.pcm RTOutFileType = F # PS = Target respose stage PSFilterType = T PSInterpolationType = S PSMultExponent = 3 PSFilterLen = 65535 PSNumPoints = 0 PSPointsFile = pa-44.1.txt PSMagType = D PSOutWindow = 65536 PSNormFactor = 1.0 PSNormType = E PSOutFile = rps.pcm PSOutFileType = F # Minimum phase filter extraction stage MSMultExponent = 3 MSOutWindow = 65536 MSFilterDelay = 683 MSNormFactor = 1.0 MSNormType = E # MSOutFile = rms.pcm MSOutFileType = F # Test convolution stage TCNormFactor = 0.0 TCNormType = M TCOutFile = rtc.pcm TCOutFileType = F drc-3.2.2/COPYING0000644000076400001450000004362111017250554012312 0ustar denisitadm GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. drc-3.2.2/readme.txt0000644000076400001450000000211313163367107013253 0ustar denisitadmDRC: Digital Room Correction Copyright (C) 2002-2017 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 Foun dation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. You can contact the author on Internet at the following address: d.sbragion@neomerica.it All the documentation for DRC is under the doc subdirectory and is available in html format. The html is also available on-line at: - http://drc-fir.sourceforge.net/doc/drc.html The official DRC home page is at: - http://drc-fir.sourceforge.net/ drc-3.2.2/drc-3.2.2.lsm0000644000076400001450000000110013162151444013167 0ustar denisitadmBegin4 Title: DRC: Digital Room Correction Version: 3.2.2 Entered-date: 2017-10-01 Description: DRC generates digital room correction FIR filters to be used within HiFi systems in conjunction with real time convolution engines like BruteFIR. Keywords: digital room correction, real time equalization, fir filters Author: d.sbragion@neomerica.it (Denis Sbragion) Maintained-by: d.sbragion@neomerica.it (Denis Sbragion), Primary-site: drc-fir.sourceforge.net Alternate-site: Original-site: Platforms: Linux, POSIX, Win32 Copying-policy: GPL End