Skip to content

Commit ce1f9b7

Browse files
committed
Added DT990 response to OME and tested
1 parent 9d12bb1 commit ce1f9b7

12 files changed

+257
-141
lines changed

Diff for: python/tests/test_OME.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import loudness as ln
2+
3+
def plotResponse(freqPoints, dataPoints, freqsInterp, responseInterp,
4+
ylim=(-40,10)):
5+
plt.semilogx(freqsInterp, responseInterp)
6+
if np.any(dataPoints):
7+
plt.semilogx(freqPoints, dataPoints, 'o')
8+
plt.xlim(20,20e3)
9+
plt.ylim(ylim)
10+
plt.xlabel("Frequency, Hz")
11+
plt.ylabel("Response, dB")
12+
13+
def plotCombined(author="",fieldType=""):
14+
freqs = np.arange(20,20000,2)
15+
ome = ln.OME(author, fieldType)
16+
ome.interpolateResponse(freqs)
17+
response = ome.getResponse()
18+
freqPoints = np.array(ome.getFreqPoints())
19+
middleEarPoints = np.zeros(freqPoints.size)
20+
outerEarPoints = np.zeros(freqPoints.size)
21+
if author:
22+
middleEarPoints = np.array(ome.getMiddleEardB())
23+
if author == "CHEN_ETAL":
24+
ylim = (-40, 10)
25+
elif "ANSI" in author:
26+
ylim = (-40, 0)
27+
else:
28+
ylim = (-5, 20)
29+
if fieldType:
30+
outerEarPoints = np.array(ome.getOuterEardB())
31+
if fieldType == "DT990":
32+
plotResponse(freqPoints, None, freqs, response, ylim)
33+
else:
34+
plotResponse(freqPoints, outerEarPoints + middleEarPoints, freqs, response, ylim)
35+
36+
plt.figure(1)
37+
plotCombined("ANSI")
38+
plt.figure(2)
39+
plotCombined("CHEN_ETAL")
40+
plt.figure(2)
41+
plotCombined("ANSI_HPF")
42+
plt.figure(3)
43+
plotCombined("", "ANSI_FREEFIELD")
44+
plt.figure(4)
45+
plotCombined("", "ANSI_DIFFUSEFIELD")
46+
plt.figure(5)
47+
plotCombined("", "DT990")
48+
plt.figure(6)
49+
plotCombined("ANSI", "ANSI_FREEFIELD")
50+
plt.figure(7)
51+
plotCombined("ANSI", "DT990")

Diff for: src/Models/DynamicLoudnessCH.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,10 @@ namespace loudness{
190190
*/
191191
if(pathToFilterCoefs_.empty())
192192
{
193-
OME::MiddleEarType middleEar = OME::CHEN_ETAL;
194-
OME::OuterEarType outerEar = OME::ANSI_FREE;
195-
193+
string middleEar = "CHEN_ETAL";
194+
string outerEar = "ANSI_FREE";
196195
if(diffuseField_)
197-
outerEar = OME::ANSI_DIFFUSE;
196+
outerEar = "ANSI_DIFFUSE";
198197

199198
modules_.push_back(unique_ptr<Module>
200199
(new WeightSpectrum(middleEar, outerEar)));

Diff for: src/Models/DynamicLoudnessGM.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,12 @@ namespace loudness{
245245
*/
246246
if(weightSpectrum)
247247
{
248-
OME::MiddleEarType middleEar = OME::ANSI;
249-
OME::OuterEarType outerEar = OME::ANSI_FREE;
248+
string middleEar = "ANSI";
249+
string outerEar = "ANSI_FREE";
250250
if(hpf_)
251-
middleEar = OME::ANSI_HPF;
251+
middleEar = "ANSI_HPF";
252252
if(diffuseField_)
253-
outerEar = OME::ANSI_DIFFUSE;
253+
outerEar = "ANSI_DIFFUSE";
254254

255255
modules_.push_back(unique_ptr<Module>
256256
(new WeightSpectrum(middleEar, outerEar)));

Diff for: src/Models/SteadyLoudnessANSIS3407.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ namespace loudness{
5959
/*
6060
* Weighting filter
6161
*/
62-
OME::MiddleEarType middleEar = OME::ANSI;
63-
OME::OuterEarType outerEar = OME::ANSI_FREE;
62+
string middleEar = "ANSI";
63+
string outerEar = "ANSI_FREE";
6464
if(diffuseField_)
65-
outerEar = OME::ANSI_DIFFUSE;
65+
outerEar = "ANSI_DIFFUSE";
6666

6767
modules_.push_back(unique_ptr<Module>
6868
(new WeightSpectrum(middleEar, outerEar)));
@@ -89,4 +89,3 @@ namespace loudness{
8989
}
9090

9191
}
92-

Diff for: src/Modules/WeightSpectrum.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ namespace loudness{
2626
weights_(weights),
2727
usingOME_(false)
2828
{}
29-
WeightSpectrum::WeightSpectrum(OME::MiddleEarType middleEarType,
30-
OME::OuterEarType outerEarType) :
29+
30+
WeightSpectrum::WeightSpectrum(const string& middleEarType, const string& outerEarType) :
3131
Module("WeightSpectrum"),
3232
ome_(middleEarType, outerEarType),
3333
usingOME_(true)
@@ -39,9 +39,10 @@ namespace loudness{
3939
{
4040
if(usingOME_)
4141
{
42-
weights_.assign(input.getNChannels(),0.0);
43-
ome_.interpolateResponse(input.getCentreFreqs(), weights_);
42+
ome_.interpolateResponse(input.getCentreFreqs());
43+
weights_ = ome_.getResponse();
4444
}
45+
4546
if((int)weights_.size() != input.getNChannels())
4647
{
4748
LOUDNESS_WARNING(name_

Diff for: src/Modules/WeightSpectrum.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ namespace loudness{
5656
* @param middleEarType The middle ear type.
5757
* @param outerEarType The outer ear type.
5858
*/
59-
WeightSpectrum(OME::MiddleEarType middleEarType = OME::ANSI,
60-
OME::OuterEarType outerEarType = OME::ANSI_FREE);
59+
WeightSpectrum(const string& middleEarType,const string& outerEarType);
6160

6261
virtual ~WeightSpectrum();
6362

Diff for: src/Support/AuditoryTools.cpp

+118-60
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ namespace loudness{
129129
}
130130
}
131131

132-
OME::OME(MiddleEarType middleEarType, OuterEarType outerEarType) :
132+
OME::OME(const string& middleEarType, const string& outerEarType) :
133133
middleEarType_(middleEarType),
134134
outerEarType_(outerEarType)
135135
{
@@ -158,106 +158,164 @@ namespace loudness{
158158
-7, -9.2, -10.2, -12.2, -10.8, -10.1, -12.7, -15, -18.2,
159159
-23.8, -32.3, -45.5, -50};
160160

161+
//can get away with the same freq spec as ANSI standard
161162
Real midChenEtAl[41] = {-100, -33, -28.5, -23.6, -19.4, -16.4, -13.4,
162163
-10.3, -8, -6.3, -4.7, -3.7, -2.7, -2.5, -1.9, -1.8, -2.1, -2.4,
163164
-2.4, -2.6, -3.7, -5.5 , -6.8, -11.4, -14.4, -11.3, -11 , -10.5,
164165
-10.9, -12.9, -13.9, -16.4, -15.6, -15.1, -16.8, -18.9, -20.9,
165166
-21.8, -22.3, -23.2, -24};
166167

167-
//put data into vectors
168-
freqVec_.assign(freqs, freqs + 41);
168+
//Beyerdynamic DT990 requires own sample points
169+
Real phoneFreqs[86] = {0, 5, 11, 17, 23, 29, 35, 41, 46, 52, 58, 64, 70,
170+
76, 82, 88, 101, 116, 133, 153, 176, 202, 232, 266, 306, 352, 404,
171+
464, 533, 612, 703, 808, 928, 1066, 1224, 1406, 1615, 1856, 2131,
172+
2448, 2813, 3231, 3711, 3928, 4144, 4396, 4897, 5215, 5437, 5625,
173+
5780, 6110, 6500, 6800, 7422, 7920, 8400, 8526, 8830, 9000, 9160,
174+
9230, 9360, 9650, 9900, 10500, 10900, 11250, 11700, 12200, 12500,
175+
12923, 13500, 14000, 14350, 14600, 14750, 14845, 15350, 16100,
176+
16700, 17200, 17750, 18420, 19587, 20000};
169177

170-
switch(middleEarType_)
178+
Real dt990[86] = {-6.45, -6.45, -7.48, -5.75, -3.69, -2.52, -1.61,
179+
-0.71, -0.42, 0.13, 0.24, -0.51, 0.56, 1.61, 2.02, 2.28, 2.6 ,
180+
2.79, 2.82, 2.69, 2.43, 2.09, 1.68, 1.31, 0.77, 0.15, -0.31,
181+
-0.64, -0.96, -1.36, -1.41, -1.16, -0.52, 0. , 1.24, 1.84, 2.8 ,
182+
4.28, 5.77, 7.5 , 8.39, 7.2 , 4.3 , 3.37, 4. , 4.52, 2.25,
183+
1.36, 2.26, 4.69, 7.01, 9.37, 9.6 , 9.66, 7.8 , 6.07, 8.25,
184+
8.9 , 7.84, 5.42, 2.24, 0.73, -0.08, 0.69, 1.23, 2.01, 1.47,
185+
0.8 , 0.54, 3.06, 3.5 , 1.79, -3.52, -7.86, -8.68, -9.81, -7.1 ,
186+
-5.09, -1.14, 0.02, 1.6 , 0.25, -2.8 , -3.97, -7.45, -6.8 };
187+
188+
//frequencies
189+
freqPoints_.assign(freqs, freqs + 41);
190+
191+
//Middle ear
192+
if(middleEarType_ == "ANSI")
193+
middleEardB_.assign(midANSI, midANSI + 41);
194+
else if(middleEarType_ == "ANSI_HPF")
195+
middleEardB_.assign(midANSI, midANSI + 41);
196+
else if(middleEarType_ == "CHEN_ETAL")
197+
middleEardB_.assign(midChenEtAl, midChenEtAl + 41);
198+
else
199+
middleEarType_ = "";
200+
201+
//Outer ear
202+
usingPhones_ = false;
203+
if(outerEarType_ == "ANSI_FREEFIELD")
171204
{
172-
case ANSI:
173-
{
174-
middleEardB_.assign(midANSI, midANSI + 41);
175-
break;
176-
}
177-
case ANSI_HPF:
178-
{
179-
middleEardB_.assign(midANSI, midANSI + 41);
180-
break;
181-
}
182-
case CHEN_ETAL:
183-
{
184-
middleEardB_.assign(midChenEtAl, midChenEtAl + 41);
185-
break;
186-
}
187-
default:
188-
{
189-
middleEardB_.assign(midANSI, midANSI + 41);
190-
middleEarType_ = ANSI;
191-
}
205+
outerEardB_.assign(freeANSI, freeANSI + 41);
192206
}
193-
switch(outerEarType_)
207+
else if(outerEarType_ == "ANSI_DIFFUSEFIELD")
194208
{
195-
case ANSI_FREE:
196-
{
197-
outerEardB_.assign(freeANSI, freeANSI + 41);
198-
break;
199-
}
200-
case ANSI_DIFFUSE:
201-
{
202-
outerEardB_.assign(diffuseANSI, diffuseANSI + 41);
203-
break;
204-
}
205-
default:
206-
{
207-
outerEardB_.assign(freeANSI, freeANSI + 41);
208-
outerEarType_ = ANSI_FREE;
209-
}
209+
outerEardB_.assign(diffuseANSI, diffuseANSI + 41);
210+
}
211+
else if(outerEarType_ == "DT990")
212+
{
213+
outerEardB_.assign(dt990, dt990 + 86);
214+
phoneFreqPoints_.assign(phoneFreqs, phoneFreqs+86);
215+
usingPhones_ = true;
216+
}
217+
else
218+
{
219+
outerEarType_ = "";
210220
}
211221
}
212222

213-
void OME::setMiddleEarType(MiddleEarType middleEarType)
223+
void OME::setMiddleEarType(const string& middleEarType)
214224
{
215225
middleEarType_ = middleEarType;
216226
}
217227

218-
void OME::setOuterEarType(OuterEarType outerEarType)
228+
void OME::setOuterEarType(const string& outerEarType)
219229
{
220230
outerEarType_ = outerEarType;
221231
}
222-
bool OME::interpolateResponse(const RealVec &freqs, RealVec &response)
232+
bool OME::interpolateResponse(const RealVec &freqs)
223233
{
224-
if(freqs.size() != response.size())
234+
if(freqs.empty())
225235
{
226-
LOUDNESS_ERROR("OME: Input vectors (freqs and response) are not equal");
236+
LOUDNESS_ERROR("OME: Input vector has no elements.");
227237
return 0;
228238
}
229239
else
230240
{
241+
response_.resize(freqs.size(), 0.0);
242+
231243
//load the data into vectors
232244
getData();
233245

234246
//the spline
235247
spline s;
236248

237249
//middle ear
238-
s.set_points(freqVec_, middleEardB_);
239-
for(unsigned int i=0; i<freqs.size(); i++)
250+
if(!middleEarType_.empty())
240251
{
241-
if((freqs[i]<=75) && (middleEarType_ == ANSI_HPF))
242-
response[i] = -14.6; //Post HPF correction
243-
else if(freqs[i]>=freqVec_[40])
244-
response[i] = middleEardB_[40];
245-
else
246-
response[i] = s(freqs[i]);
252+
s.set_points(freqPoints_, middleEardB_);
253+
for(unsigned int i=0; i<freqs.size(); i++)
254+
{
255+
if((freqs[i]<=75) && (middleEarType_ == "ANSI_HPF"))
256+
response_[i] = -14.6; //Post HPF correction
257+
else if(freqs[i]>=freqPoints_[40])
258+
response_[i] = middleEardB_[40];
259+
else
260+
response_[i] = s(freqs[i]);
261+
}
262+
}
263+
else
264+
{
265+
LOUDNESS_WARNING("OME: No middle ear filter used.");
247266
}
248267

249268
//outer ear
250-
s.set_points(freqVec_, outerEardB_);
251-
for(unsigned int i=0; i<freqs.size(); i++)
269+
if(!outerEarType_.empty())
252270
{
253-
if(freqs[i]>=freqVec_[40])
254-
response[i] += outerEardB_[40];
271+
Real lastFreq = freqPoints_.back();
272+
Real lastDataPoint = outerEardB_.back();
273+
if(usingPhones_)
274+
{
275+
lastFreq = phoneFreqPoints_.back();
276+
s.set_points(phoneFreqPoints_, outerEardB_);
277+
}
255278
else
256-
response[i] += s(freqs[i]);
279+
{
280+
s.set_points(freqPoints_, outerEardB_);
281+
}
282+
for(unsigned int i=0; i<freqs.size(); i++)
283+
{
284+
if(freqs[i]>=lastFreq)
285+
response_[i] += lastDataPoint;
286+
else
287+
response_[i] += s(freqs[i]);
288+
}
289+
}
290+
else
291+
{
292+
LOUDNESS_WARNING("OME: No outer ear filter used.");
257293
}
258294

259-
return 0;
295+
return 1;
260296
}
261297
}
262-
}
263298

299+
const RealVec& OME::getResponse() const
300+
{
301+
return response_;
302+
}
303+
304+
const RealVec& OME::getMiddleEardB() const
305+
{
306+
return middleEardB_;
307+
}
308+
309+
const RealVec& OME::getOuterEardB() const
310+
{
311+
return outerEardB_;
312+
}
313+
314+
const RealVec& OME::getFreqPoints() const
315+
{
316+
if (usingPhones_)
317+
return phoneFreqPoints_;
318+
else
319+
return freqPoints_;
320+
}
321+
}

0 commit comments

Comments
 (0)