Пример #1
0
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
Пример #2
0
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
Пример #3
0
def test_third_low(third_real):
    generated = third_low(12.5, 20000)
    real = third_real / 2**(1 / 6)
    assert_array_almost_equal(generated, real)
Пример #4
0
def test_third_low():
    generated = third_low(12.5, 20000)
    real = third_real / 2**(1 / 6)
    assert_array_almost_equal(generated, real)
Пример #5
0
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
Пример #6
0
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
Пример #7
0
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
Пример #8
0
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