def clarity(time, signal, fs, bands=None): """ Clarity :math:`C_i` determined from an impulse response. :param time: Time in miliseconds (e.g.: 50, 80). :param signal: Impulse response. :type signal: :class:`np.ndarray` :param fs: Sample frequency. :param bands: Bands of calculation (optional). Only support standard octave and third-octave bands. :type bands: :class:`np.ndarray` """ band_type = _check_band_type(bands) if band_type == 'octave': low = octave_low(bands[0], bands[-1]) high = octave_high(bands[0], bands[-1]) elif band_type == 'third': low = third_low(bands[0], bands[-1]) high = third_high(bands[0], bands[-1]) c = np.zeros(bands.size) for band in range(bands.size): filtered_signal = bandpass(signal, low[band], high[band], fs, order=8) h2 = filtered_signal**2.0 t = int((time / 1000.0) * fs + 1) c[band] = 10.0 * np.log10((np.sum(h2[:t]) / np.sum(h2[t:]))) return c
def clarity(time, signal, fs, bands=None): """ Clarity :math:`C_i` determined from an impulse response. :param time: Time in miliseconds (e.g.: 50, 80). :param signal: Impulse response. :type signal: :class:`np.ndarray` :param fs: Sample frequency. :param bands: Bands of calculation (optional). Only support standard octave and third-octave bands. :type bands: :class:`np.ndarray` """ band_type = _check_band_type(bands) if band_type is 'octave': low = octave_low(bands[0], bands[-1]) high = octave_high(bands[0], bands[-1]) elif band_type is 'third': low = third_low(bands[0], bands[-1]) high = third_high(bands[0], bands[-1]) c = np.zeros(bands.size) for band in range(bands.size): filtered_signal = bandpass(signal, low[band], high[band], fs, order=3) h2 = filtered_signal**2.0 t = int((time / 1000.0) * fs + 1) c[band] = 10.0 * np.log10((np.sum(h2[:t]) / np.sum(h2[t:]))) return c
def test_octave_low(octave_real): generated = octave_low(16, 16000) real = real = octave_real / np.sqrt(2) assert_array_almost_equal(generated, real)
def test_octave_low(): generated = octave_low(16, 16000) real = real = octave_real / np.sqrt(2) assert_array_almost_equal(generated, real)
def t60_impulse(file_name, bands, rt='t30'): """ Reverberation time from a WAV impulse response. :param file_name: name of the WAV file containing the impulse response. :param bands: Octave or third bands as NumPy array. :param rt: Reverberation time estimator. It accepts `'t30'`, `'t20'`, `'t10'` and `'edt'`. :returns: Reverberation time :math:`T_{60}` """ fs, raw_signal = wavfile.read(file_name) band_type = _check_band_type(bands) if band_type is 'octave': low = octave_low(bands[0], bands[-1]) high = octave_high(bands[0], bands[-1]) elif band_type is 'third': low = third_low(bands[0], bands[-1]) high = third_high(bands[0], bands[-1]) rt = rt.lower() if rt == 't30': init = -5.0 end = -35.0 factor = 2.0 elif rt == 't20': init = -5.0 end = -25.0 factor = 3.0 elif rt == 't10': init = -5.0 end = -15.0 factor = 6.0 elif rt == 'edt': init = 0.0 end = -10.0 factor = 6.0 t60 = np.zeros(bands.size) for band in range(bands.size): # Filtering signal filtered_signal = bandpass(raw_signal, low[band], high[band], fs, order=3) abs_signal = np.abs(filtered_signal) / np.max(np.abs(filtered_signal)) # Schroeder integration sch = np.cumsum(abs_signal[::-1]**2)[::-1] sch_db = 10.0 * np.log10(sch / np.max(sch)) # Linear regression sch_init = sch_db[np.abs(sch_db - init).argmin()] sch_end = sch_db[np.abs(sch_db - end).argmin()] init_sample = np.where(sch_db == sch_init)[0][0] end_sample = np.where(sch_db == sch_end)[0][0] x = np.arange(init_sample, end_sample + 1) / fs y = sch_db[init_sample:end_sample + 1] slope, intercept, r_value, p_value, std_err = stats.linregress(x, y) # Reverberation time (T30, T20, T10 or EDT) db_regress_init = (init - intercept) / slope db_regress_end = (end - intercept) / slope t60[band] = factor * (db_regress_end - db_regress_init) return t60
def t60_impulse(file_name, bands, rt='t30'): # pylint: disable=too-many-locals """ Reverberation time from a WAV impulse response. :param file_name: name of the WAV file containing the impulse response. :param bands: Octave or third bands as NumPy array. :param rt: Reverberation time estimator. It accepts `'t30'`, `'t20'`, `'t10'` and `'edt'`. :returns: Reverberation time :math:`T_{60}` """ fs, raw_signal = wavfile.read(file_name) band_type = _check_band_type(bands) if band_type == 'octave': low = octave_low(bands[0], bands[-1]) high = octave_high(bands[0], bands[-1]) elif band_type == 'third': low = third_low(bands[0], bands[-1]) high = third_high(bands[0], bands[-1]) rt = rt.lower() if rt == 't30': init = -5.0 end = -35.0 factor = 2.0 elif rt == 't20': init = -5.0 end = -25.0 factor = 3.0 elif rt == 't10': init = -5.0 end = -15.0 factor = 6.0 elif rt == 'edt': init = 0.0 end = -10.0 factor = 6.0 t60 = np.zeros(bands.size) for band in range(bands.size): # Filtering signal filtered_signal = bandpass(raw_signal, low[band], high[band], fs, order=8) abs_signal = np.abs(filtered_signal) / np.max(np.abs(filtered_signal)) # Schroeder integration sch = np.cumsum(abs_signal[::-1]**2)[::-1] sch_db = 10.0 * np.log10(sch / np.max(sch)) # Linear regression sch_init = sch_db[np.abs(sch_db - init).argmin()] sch_end = sch_db[np.abs(sch_db - end).argmin()] init_sample = np.where(sch_db == sch_init)[0][0] end_sample = np.where(sch_db == sch_end)[0][0] x = np.arange(init_sample, end_sample + 1) / fs y = sch_db[init_sample:end_sample + 1] slope, intercept = stats.linregress(x, y)[0:2] # Reverberation time (T30, T20, T10 or EDT) db_regress_init = (init - intercept) / slope db_regress_end = (end - intercept) / slope t60[band] = factor * (db_regress_end - db_regress_init) return t60
def drr_impulse(signal, fs, bands=None, debug=False): """ Clarity :math:`C_i` determined from an impulse response. :param time: Time in miliseconds (e.g.: 50, 80). :param signal: Impulse response. :type signal: :class:`np.ndarray` :param fs: Sample frequency. :param bands: Bands of calculation (optional). Only support standard octave and third-octave bands. :type bands: :class:`np.ndarray` """ band_type = _check_band_type(bands) if band_type == 'octave': low = octave_low(bands[0], bands[-1]) high = octave_high(bands[0], bands[-1]) elif band_type == 'third': low = third_low(bands[0], bands[-1]) high = third_high(bands[0], bands[-1]) direct_range = int( 2.5e-3 * fs) #2.5ms window around the peak is what is used by ACE challenge if bands is not None: #print('\n\nall\n\n') drr = np.zeros(bands.size) for band in range(bands.size): filtered_signal = bandpass(signal, low[band], high[band], fs, order=8) h2 = np.abs(filtered_signal) * np.abs(filtered_signal) onset = np.argmax(np.abs(h2)) if onset > direct_range: direct = h2[onset - direct_range:onset + direct_range] reverb = np.concatenate((h2[:onset - direct_range - 1], h2[onset + direct_range + 1:])) else: direct = h2[:2 * direct_range] reverb = h2[2 * direct_range + 1:] drr[band] = 10.0 * np.log10( (np.sum(np.abs(direct)) / np.sum(np.abs(reverb)))) else: h2 = np.abs(signal) * np.abs(signal) onset = np.argmax(np.abs(h2)) if onset > direct_range: direct = h2[onset - direct_range:onset + direct_range] reverb = np.concatenate( (h2[:onset - direct_range - 1], h2[onset + direct_range + 1:])) else: direct = h2[:2 * direct_range] reverb = h2[2 * direct_range + 1:] drr = 10.0 * np.log10( (np.sum(np.abs(direct)) / np.sum(np.abs(reverb)))) if debug: print(f'Onset : {onset}') print(f'direct : {direct}') print(f'reverb : {reverb}') print(f'drr before log : {((np.sum(direct) / np.sum(reverb)))}') print(f'drr final : {drr}') return drr
def t60_impulse(raw_signal, fs): # pylint: disable=too-many-locals """ Reverberation time from a WAV impulse response. :param file_name: name of the WAV file containing the impulse response. :param bands: Octave or third bands as NumPy array. :param rt: Reverberation time estimator. It accepts `'t30'`, `'t20'`, `'t10'` and `'edt'`. :returns: Reverberation time :math:`T_{60}` """ bands = np.array([62.5, 125, 250, 500, 1000, 2000]) if np.max(raw_signal) == 0 and np.min(raw_signal) == 0: print('came 1') return .5 # fs, raw_signal = wavfile.read(file_name) band_type = _check_band_type(bands) # if band_type == 'octave': low = octave_low(bands[0], bands[-1]) high = octave_high(bands[0], bands[-1]) # elif band_type == 'third': # low = third_low(bands[0], bands[-1]) # high = third_high(bands[0], bands[-1]) init = -0.0 end = -60.0 factor = 1.0 bands = bands[3:5] low = low[3:5] high = high[3:5] t60 = np.zeros(bands.size) for band in range(bands.size): # Filtering signal filtered_signal = bandpass(raw_signal, low[band], high[band], fs, order=8) abs_signal = np.abs(filtered_signal) / np.max(np.abs(filtered_signal)) # Schroeder integration sch = np.cumsum(abs_signal[::-1]**2)[::-1] sch_db = 10.0 * np.log10(sch / np.max(sch)) if math.isnan(sch_db[1]): print('came 2') return .5 # print("leng sch_db ",sch_db.size) # print("sch_db ",sch_db) # Linear regression sch_init = sch_db[np.abs(sch_db - init).argmin()] sch_end = sch_db[np.abs(sch_db - end).argmin()] init_sample = np.where(sch_db == sch_init)[0][0] end_sample = np.where(sch_db == sch_end)[0][0] x = np.arange(init_sample, end_sample + 1) / fs y = sch_db[init_sample:end_sample + 1] slope, intercept = stats.linregress(x, y)[0:2] # Reverberation time (T30, T20, T10 or EDT) db_regress_init = (init - intercept) / slope db_regress_end = (end - intercept) / slope t60[band] = factor * (db_regress_end - db_regress_init) mean_t60 = (t60[1] + t60[0]) / 2 # print("meant60 is ", mean_t60) if math.isnan(mean_t60): print('came 3') return .5 return mean_t60
def t60_from_signal(raw_signal, fs, bands, rt='t30'): # pylint: disable=too-many-locals """ Reverberation time from a WAV impulse response. :param raw_signal: Impulse response. :type raw_signal: :class:`np.ndarray` :param fs: Sample frequency. :param bands: Octave or third bands as NumPy array. :param rt: Reverberation time estimator. It accepts `'t30'`, `'t20'`, `'t10'` and `'edt'`. :returns: Reverberation time :math:`T_{60}` """ band_type = _check_band_type(bands) if band_type == 'octave': low = octave_low(bands[0], bands[-1]) high = octave_high(bands[0], bands[-1]) elif band_type == 'third': low = third_low(bands[0], bands[-1]) high = third_high(bands[0], bands[-1]) rt = rt.lower() if rt == 't30': init = -5.0 end = -35.0 factor = 2.0 elif rt == 't20': init = -5.0 end = -25.0 factor = 3.0 elif rt == 't10': init = -5.0 end = -15.0 factor = 6.0 elif rt == 'edt': init = 0.0 end = -10.0 factor = 6.0 t60 = np.zeros(bands.size) for band in range(bands.size): # Filtering signal filtered_signal = bandpass(raw_signal, low[band], high[band], fs, order=8) abs_signal = np.abs(filtered_signal) / np.max(np.abs(filtered_signal)) # Schroeder integration sch = np.cumsum(abs_signal[::-1]**2)[::-1] sch_db = 10.0 * np.log10(sch / np.max(sch)) # Linear regression sch_init = sch_db[np.abs(sch_db - init).argmin()] sch_end = sch_db[np.abs(sch_db - end).argmin()] init_sample = np.where(sch_db == sch_init)[0][0] end_sample = np.where(sch_db == sch_end)[0][0] x = np.arange(init_sample, end_sample + 1) / fs y = sch_db[init_sample:end_sample + 1] slope, intercept = stats.linregress(x, y)[0:2] # Reverberation time (T30, T20, T10 or EDT) db_regress_init = (init - intercept) / slope db_regress_end = (end - intercept) / slope t60[band] = factor * (db_regress_end - db_regress_init) return t60