Code_TYMPAN  4.4.0
Industrial site acoustic simulation
sonie_zwicker_1991.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2014> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #include <cmath>
17 
19 #include "sonie_zwicker_1991.h"
20 
21 const unsigned short sonie::Nbandes3Oct = 28;
22 const double sonie::RAP[] = {45, 55, 65, 71, 80, 90, 100, 120};
23 
24 const double sonie::DLL[8][11] = {
25  {-32, -24, -16, -10, -5, 0, -7, -3, 0, -2, 0}, {-29, -22, -15, -10, -4, 0, -7, -2, 0, -2, 0},
26  {-27, -19, -14, -9, -4, 0, -6, -2, 0, -2, 0}, {-25, -17, -12, -9, -3, 0, -5, -2, 0, -2, 0},
27  {-23, -16, -11, -7, -3, 0, -4, -1, 0, -1, 0}, {-20, -14, -10, -6, -3, 0, -4, -1, 0, -1, 0},
28  {-18, -12, -9, -6, -2, 0, -3, -1, 0, -1, 0}, {-15, -10, -8, -4, -2, 0, -3, -1, 0, -1, 0}};
29 
30 const double sonie::LTQ[] = {30, 18, 12, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
31 
32 const double sonie::A0[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.5, -1.6, -3.2, -5.4, -5.6, -4, -1.5, 2, 5, 12};
33 
34 const double sonie::DDF[] = {0, 0, 0.5, 0.9, 1.2, 1.6, 2.3, 2.8, 3, 2,
35  0, -1.4, -2, -1.9, -1, 0.5, 3, 4, 4.3, 4};
36 
37 const double sonie::DCB[] = {-0.25, -0.6, -0.8, -0.8, -0.5, 0, 0.5, 1.1, 1.5, 1.7,
38  1.8, 1.8, 1.7, 1.6, 1.4, 1.2, 0.8, 0.5, 0, -0.5};
39 
40 const double sonie::ZUP[] = {0.9, 1.8, 2.8, 3.5, 4.4, 5.4, 6.6, 7.9, 9.2, 10.6, 12.3,
41  13.8, 15.2, 16.7, 18.1, 19.3, 20.6, 21.8, 22.7, 23.6, 24};
42 
43 const double sonie::RNS[] = {21.5, 18, 15.1, 11.5, 9, 6.1, 4.4, 3.1, 2.13,
44  1.36, 0.82, 0.42, 0.30, 0.22, 0.15, 0.10, 0.035, 0};
45 
46 const double sonie::USL[18][8] = {
47  {13, 8.2, 6.3, 5.5, 5.5, 5.5, 5.5, 5.5}, {9, 7.5, 6, 5.1, 4.5, 4.5, 4.5, 4.5},
48  {7.8, 6.7, 5.6, 4.9, 4.4, 3.9, 3.9, 3.9}, {6.2, 5.4, 4.6, 4.0, 3.5, 3.2, 3.2, 3.2},
49  {4.5, 3.8, 3.6, 3.2, 2.9, 2.7, 2.7, 2.7}, {3.7, 3.0, 2.8, 2.35, 2.2, 2.2, 2.2, 2.2},
50  {2.9, 2.3, 2.1, 1.9, 1.8, 1.7, 1.7, 1.7}, {2.4, 1.7, 1.5, 1.35, 1.3, 1.3, 1.3, 1.3},
51  {1.95, 1.45, 1.3, 1.15, 1.1, 1.1, 1.1, 1.1}, {1.5, 1.2, 0.94, 0.86, 0.82, 0.82, 0.82, 0.82},
52  {0.72, 0.67, 0.64, 0.63, 0.62, 0.62, 0.62, 0.62}, {0.59, 0.53, 0.51, 0.50, 0.42, 0.42, 0.42, 0.42},
53  {0.40, 0.33, 0.26, 0.24, 0.24, 0.22, 0.22, 0.22}, {0.27, 0.21, 0.20, 0.18, 0.17, 0.17, 0.17, 0.17},
54  {0.16, 0.15, 0.14, 0.12, 0.11, 0.11, 0.11, 0.11}, {0.12, 0.11, 0.10, 0.08, 0.08, 0.08, 0.08, 0.08},
55  {0.09, 0.08, 0.07, 0.06, 0.06, 0.06, 0.06, 0.05}, {0.06, 0.05, 0.03, 0.02, 0.02, 0.02, 0.02, 0.02}};
56 
57 sonie::sonie(double* vectToct, const unsigned short& champ /*= 0*/) : VectNiv3Oct(vectToct), Champ(champ)
58 {
59  N_Tot = 0.0;
60  LN = 0.0;
61  N_Specif = new double[240];
62  BarkAxis = new double[240];
63  _isOk = validation();
64 
65  // Vrification des donnes d'entre et execution si ok
66  if (_isOk)
67  {
68  exec();
69  }
70 }
71 
73 {
74  delete[] N_Specif;
75  N_Specif = 0;
76  delete[] BarkAxis;
77  BarkAxis = 0;
78 }
79 
81 {
82  // Vrification de la valeur de Champ (0 ou 1)
83  if ((Champ != 0) && (Champ != 1))
84  {
85  return false;
86  }
87 
88  // Vrification du maximum et du minimum
89  for (unsigned short i = 0; i < 28; i++)
90  {
91  if ((VectNiv3Oct[i] > 120.0) || (VectNiv3Oct[i] < -60.0))
92  {
93  return false;
94  }
95  }
96 
97  return true;
98 }
99 
100 double sonie::calcIsoSonie(const double& val)
101 {
102  if (val >= 1) // Calcul du niveau d'isosonie pour pour LN >= 40 phones ou N >= 1 sone
103  {
104  return 10 * ::log10(val) / ::log10(2.0) + 40;
105  }
106  else // Calcul du niveau d'isosonie pour LN < 40 phones ou N < 1 sone
107  {
108  double phone = 40 * ::pow((val + 0.0005), 0.35);
109  return phone < 3.0 ? 3.0 : phone;
110  }
111 
112  return 0.0;
113 }
114 
116 {
117  // Cration et initialisation des tableaux (dans l'ordre de leur mise
118  // en oeuvre dans la version MATLAB
119  double TI[11] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
120  double GI[3] = {0.0, 0.0, 0.0};
121  double FNGI[3] = {0.0, 0.0, 0.0};
122  double LCB[3] = {0.0, 0.0, 0.0};
123  double LE[21] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
124  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
125  double NM[21] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
126  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
127  double NS[240];
128  for (unsigned short i = 0; i < 240; i++)
129  {
130  NS[i] = 0.0;
131  } // Initialisation
132 
133  // Correction des niveaux des bandes de tiers d'octave d'aprs
134  // les niveaux d'isosonie (Xp) et calcul des intensits sonores
135  // pour les bandes basses frquences jusqu' 315 Hz
136  double XP = 0.0;
137  for (unsigned short i = 0, j = 0; i < 11; i++)
138  {
139  j = 0;
140  while ((VectNiv3Oct[i] > (RAP[j] - DLL[j][i])) && j < 7)
141  {
142  j++;
143  }
144 
145  XP = VectNiv3Oct[i] + DLL[j][i];
146  TI[i] = ::pow(10.0, XP / 10.0);
147  }
148 
149  // Dtermination des niveaux (LCB) dans les 3 premires bandes critiques
150  GI[0] = TI[0] + TI[1] + TI[2] + TI[3] + TI[4] + TI[5];
151  GI[1] = TI[6] + TI[7] + TI[8];
152  GI[2] = TI[9] + TI[10];
153 
154  for (unsigned short i = 0; i < 3; i++)
155  {
156  FNGI[i] = 10 * ::log10(GI[i]);
157  }
158 
159  for (unsigned short i = 0; i < 3; i++)
160  {
161  if (GI[i] > 0.0)
162  {
163  LCB[i] = FNGI[i];
164  }
165  }
166 
167  // Calcul de la sonie principale
168 
169  const unsigned short NbandesCritiques = 20;
170  const double S = 0.25;
171  const double BarkStep = 0.1;
172 
173  for (unsigned short i = 0; i < NbandesCritiques + 1; i++)
174  {
175  LE[i] = VectNiv3Oct[i + 8];
176 
177  if (i < 3)
178  {
179  LE[i] = LCB[i];
180  }
181 
182  LE[i] = LE[i] - A0[i];
183  NM[i] = 0; // Cette ligne est elle utile dans la mesure ou NM a t initialise ?
184 
185  if (Champ == 1)
186  {
187  LE[i] = LE[i] + DDF[i];
188  }
189 
190  if (LE[i] > LTQ[i])
191  {
192  LE[i] = LE[i] - DCB[i];
193  double MP1 = 0.0635 * ::pow(10.0, 0.025 * LTQ[i]);
194  double MP2_1 = ::pow(10.0, (LE[i] - LTQ[i]) / 10);
195  double MP2 = ::pow((1.0 - S + (S * MP2_1)), 0.25) - 1.0;
196 
197  NM[i] = MP1 * MP2;
198 
199  if (NM[i] <= 0.0)
200  {
201  NM[i] = 0.0;
202  }
203  }
204  }
205 
206  // Correction sur la sonie spcifique dans la premire bande critique en prenant
207  // en compte la dpendance au seuil absolu d'audition pour le niveau de cette bande
208  double KORRY = 0.4 + (0.32 * ::pow(NM[0], 0.2));
209  if (KORRY > 1.0)
210  {
211  KORRY = 1.0;
212  }
213 
214  NM[0] = NM[0] * KORRY;
215 
216  // Dfinition de la valeur initiale
217  unsigned short IZ = 0;
218  unsigned short IG = 0;
219  double Z = 0.1;
220  double Z1 = 0.0;
221  double Z2 = 0.0;
222  double DZ = 0.0;
223  double N = 0.0;
224  double N1 = 0.0;
225  double N2 = 0.0;
226  double k = 0.0;
227  double ZUPI = 0.0;
228 
229  // valeurs pour toutes les bandes critiques
230  for (unsigned short i = 0, j = 0; i < NbandesCritiques; i++)
231  {
232  ZUPI = ZUP[i] + 0.0001;
233  if (i > 0)
234  {
235  IG = i - 1;
236  } // A vrifier
237  if (IG > 7)
238  {
239  IG = 7;
240  } // Les valeurs des pentes (USL) pour les bandes suprieures l'indice 8 sont identiques
241 
242  while (Z1 < ZUPI)
243  {
244  if (N1 <= NM[i]) // pour les parties plates de la courbe de sonie spcifique
245  {
246  if (N1 < NM[i])
247  {
248  j = 0;
249  // on dtermine ici le niveau considrer pour choisir la pente
250  // (pour les cas potentiels suivants ou N1 > NM(i))
251  while ((RNS[j] > NM[i]) && (j < 17))
252  {
253  j++;
254  }
255  }
256 
257  Z2 = ZUPI;
258  N2 = NM[i];
259  N = N + N2 * (Z2 - Z1);
260  k = Z; // Initialisation de k
261 
262  while (k <= Z2)
263  {
264  NS[IZ] = N2;
265  IZ = IZ + 1;
266  k = k + BarkStep;
267  }
268 
269  Z = k;
270  }
271  else if (N1 > NM[i])
272  {
273  N2 = RNS[j];
274 
275  if (N2 < NM[i])
276  {
277  N2 = NM[i];
278  }
279 
280  DZ = (N1 - N2) / USL[j][IG];
281  Z2 = Z1 + DZ;
282 
283  if (Z2 > ZUPI)
284  {
285  Z2 = ZUPI;
286  DZ = Z2 - Z1;
287  N2 = N1 - DZ * USL[j][IG];
288  }
289  N = N + DZ * (N1 + N2) / 2;
290  k = Z; // Initialisation de k
291 
292  while (k <= Z2)
293  {
294  NS[IZ] = N1 - (k - Z1) * USL[j][IG];
295  IZ = IZ + 1;
296  k = k + BarkStep;
297  }
298 
299  Z = k;
300  }
301 
302  while ((N2 <= RNS[j]) && (j < 17))
303  {
304  j++;
305  }
306 
307  if ((N2 <= RNS[j]) && (j >= 17))
308  {
309  j = 17;
310  }
311 
312  // Initialisation des variables N1 et Z1 pour l'itration suivante.
313  Z1 = Z2;
314  N1 = N2;
315  }
316  }
317 
318  if (N < 0.0)
319  {
320  N = 0.0;
321  }
322 
323  // On arrondit la valeur a 10^(-3) prs
324  if (N <= 16.0)
325  {
326  N = static_cast<double>(ROUND(N * 1000)) / 1000.0; // On ajoute pas O.5 car c'est fait par ROUND
327  }
328  else
329  {
330  N = static_cast<double>(ROUND(N * 100)) / 100.0; // On ajoute pas O.5 car c'est fait par ROUND
331  }
332 
333  // Recopie de NS dans N_Specif
334  for (unsigned short i = 0; i < 240; i++)
335  {
336  N_Specif[i] = NS[i];
337  }
338 
339  N_Tot = N;
340 
341  // Calcul du niveau d'isosonie (en phones)
342  LN = calcIsoSonie(N_Tot);
343 }
All base classes related to 3D manipulation.
int ROUND(double a)
Compute the rounded value of a number.
Definition: 3d.h:192
double * N_Specif
Sonie Sp�cifique.
~sonie()
Destructor.
bool _isOk
Indication de bonne ex�cution du calcul.
double * BarkAxis
Vecteur des de bark sur lequel est calcul� N_specif.
static const double DCB[]
double LN
Niveau d'isosonie en phone.
double calcIsoSonie(const double &val)
Renvoie le niveau d'isosonie en phone.
sonie(double *vectToct, const unsigned short &champ=0)
Constructor.
static const double DLL[8][11]
double N_Tot
Sonie totale.
static const double RAP[]
static const double A0[]
static const double LTQ[]
static const double RNS[]
static const double ZUP[]
static const double DDF[]
static const double USL[18][8]
unsigned short Champ
Type de champ (0 = champ libre, 1 = champ diffus)
static const unsigned short Nbandes3Oct
Dimension du vecteur des valaur en 1/3 d'octave.
bool validation()
V�rification des donn�es d'entr�e.
double * VectNiv3Oct
Tableau de 28 doubles repr�sentant les valeurs par 1/3 d'octave sur la bande 25-10000 Hz.