Added code to generate narrow band data from band data and vice versa

This commit is contained in:
Anne de Jong 2020-01-17 17:00:07 +01:00
parent fe53ada328
commit c748e6cb75

View File

@ -177,8 +177,10 @@ class FilterBankDesigner:
return list(range(xstart, xend+1)) return list(range(xstart, xend+1))
def getNarrowBandFromOctaveBand(self, xl, xu, def getNarrowBandFromOctaveBand(self, xl, xu,
levels_in_bands, npoints=500): levels_in_bands, npoints=500,
"""Create a narrow band spectrum based on a spectrum in (fractional) method='flat',
scale='lin'):
"""Create a narrow band spectrum based on a spectrum in (fractional)
octave bands. The result is create such that the total energy in each octave bands. The result is create such that the total energy in each
frequency band is constant. The latter can be checked by working it frequency band is constant. The latter can be checked by working it
back to (fractional) octave bands, which is doen using the function back to (fractional) octave bands, which is doen using the function
@ -193,6 +195,11 @@ class FilterBankDesigner:
(xu+1 - xl) (xu+1 - xl)
npoints: Number of discrete frequency points in linear frequency npoints: Number of discrete frequency points in linear frequency
array. array.
method: 'flat' to give the same power for all frequencies in a
certain band.
scale: 'lin' for a linear frequency distribution. 'log' for a
logspace. Use 'log' with caution and only if you really know what
you are doing!'
Returns: Returns:
freq, levels_dB. Where levels_dB is an array of narrow band levels freq, levels_dB. Where levels_dB is an array of narrow band levels
@ -202,24 +209,79 @@ class FilterBankDesigner:
# Highest frequency of all frequencies # Highest frequency of all frequencies
fuu = self.fu(xu) fuu = self.fu(xu)
freq = np.linspace(fll, fuu, npoints) if scale == 'lin':
freq = np.linspace(fll, fuu, npoints)
elif scale == 'log':
freq = np.logspace(np.log10(fll), np.log10(fuu), npoints)
else:
raise ValueError(f'Invalid scale parameter: {scale}')
levels_narrow = np.empty_like(freq) levels_narrow = np.empty_like(freq)
for i, x in enumerate(range(xl, xu + 1)):
if method == 'flat':
for i, x in enumerate(range(xl, xu + 1)):
fl = self.fl(x)
fu = self.fu(x)
# Find the indices in the frequency array which correspond to the
# frequency band x
if x != xu:
indices_cur = np.where((freq >= fl) & (freq < fu))
else:
indices_cur = np.where((freq >= fl) & (freq <= fu))
power_cur = 10**(levels_in_bands[i] / 10)
power_narrow = power_cur / indices_cur[0].size
level_narrow = 10*np.log10(power_narrow)
levels_narrow[indices_cur] = level_narrow
return freq, levels_narrow
else:
raise ValueError('Unimplemented interpolation method')
def getOctaveBandFromNarrowBand(self, freq, levels_narrow):
"""Put all level results in a certain frequency band (`binning`), by
summing up the power.
Args:
freq: Narrow-band frequency array
levels_narrow: Narrow band power levels, should be power, not *PSD*
Returns:
(fm, levels_binned, nom_txt)
"""
# Find lower frequency xl
for x in self.xs:
xl = x
fl = self.fl(x)
if self.fl(x+1) > freq[0]:
break
# Find upper frequency xu
for x in self.xs:
xu = x
fu = self.fu(xu)
if fu >= freq[-1]:
break
freq_in_bands = []
levels_in_bands = []
nom_txt = []
for x in range(xl, xu+1):
fl = self.fl(x) fl = self.fl(x)
fu = self.fu(x) fu = self.fu(x)
# Find the indices in the frequency array which correspond to the
# frequency band x
if x != xu: if x != xu:
indices_cur = np.where((freq >= fl) & (freq < fu)) indices_cur = np.where((freq >= fl) & (freq < fu))
else: else:
indices_cur = np.where((freq >= fl) & (freq <= fu)) indices_cur = np.where((freq >= fl) & (freq <= fu))
power_cur = 10**(levels_in_bands[i] / 10) power_cur = np.sum(10**(levels_narrow[indices_cur] / 10))
power_narrow = power_cur / indices_cur[0].size levels_in_bands.append(10*np.log10(power_cur))
level_narrow = 10*np.log10(power_narrow)
levels_narrow[indices_cur] = level_narrow
return freq, levels_narrow nom_txt.append(self.nominal_txt(x))
freq_in_bands.append(self.fm(x))
return np.array(freq_in_bands), np.array(levels_in_bands), nom_txt
class OctaveBankDesigner(FilterBankDesigner): class OctaveBankDesigner(FilterBankDesigner):