Beispiel #1
0
def write_ranking_table():
    harman_inear = os.path.join(ROOT_DIR, 'compensation', 'harman_in-ear_2019v2.csv')
    harman_inear = FrequencyResponse.read_from_csv(harman_inear)
    harman_overear = os.path.join(ROOT_DIR, 'compensation', 'harman_over-ear_2018.csv')
    harman_overear = FrequencyResponse.read_from_csv(harman_overear)

    onear_rows = []
    # Over-ear
    files = list(glob(os.path.join(ROOT_DIR, 'results', 'oratory1990', 'harman_over-ear_2018', '*', '*.csv')))
    files += list(glob(os.path.join(ROOT_DIR, 'results', 'crinacle', 'gras_43ag-7_harman_over-ear_2018', '*', '*.csv')))
    for fp in files:
        row = ranking_row(fp, harman_overear, 'onear')
        if row:
            onear_rows.append(row)
    onear_rows = sorted(onear_rows, key=lambda row: float(row[1]), reverse=True)
    onear_str = tabulate(onear_rows, headers=['Name', 'Score', 'STD (dB)', 'Slope'], tablefmt='orgtbl')
    onear_str = onear_str.replace('+', '|').replace('|-', '|:')

    inear_rows = []
    # In-ear
    files = list(glob(os.path.join(ROOT_DIR, 'results', 'oratory1990', 'harman_in-ear_2019v2', '*', '*.csv')))
    files += list(glob(os.path.join(ROOT_DIR, 'results', 'crinacle', 'harman_in-ear_2019v2', '*', '*.csv')))
    for fp in files:
        row = ranking_row(fp, harman_inear, 'inear')
        if row:
            inear_rows.append(row)
    inear_str = sorted(inear_rows, key=lambda row: float(row[1]), reverse=True)
    inear_str = tabulate(inear_str, headers=['Name', 'Score', 'STD (dB)', 'Slope', 'Average (dB)'], tablefmt='orgtbl')
    inear_str = inear_str.replace('-+-', '-|-').replace('|-', '|:')

    s = f'''# Headphone Ranking
    Headphones ranked by Harman headphone listener preference scores.

    Tables include the preference score (Score), standard deviation of the error (STD), slope of the logarithimc
    regression fit of the error (Slope) for both headphone types and average of the absolute error (Average) for in-ear
    headphones. STD tells how much the headphone deviates from neutral and slope tells if the headphone is warm (< 0) or
    bright (> 0).

    Keep in mind that these numbers are calculated with deviations from Harman targets. The linked results use different
    levels of bass boost so the slope numbers here won't match the error curves you see in the linked results.

    Over-ear table includes headphones measured by oratory1990 and Crinacle using GRAS systems. Measurements from
    other databases and systems are not included because they are not compatible with measurements, targets and
    preference scoring developed by Sean Olive et al.
    
    ## Over-ear Headphones    
    {onear_str}

    ## In-ear Headphones
    {inear_str}

    '''
    with open(os.path.join(ROOT_DIR, 'results', 'RANKING.md'), 'w', encoding='utf-8') as fh:
        fh.write(re.sub('\n[ \t]+', '\n', s).strip())
Beispiel #2
0
def main():
    compensation = FrequencyResponse.read_from_csv(
        os.path.join('resources', 'innerfidelity_compensation_2016.csv'))
    compensation.center()
    for file in glob(os.path.join('data', 'adhoc', '**', '*.csv'),
                     recursive=True):
        fr = FrequencyResponse.read_from_csv(file)
        print(fr.name)
        fr.interpolate()
        fr.center()
        fr.raw += compensation.raw
        fr.write_to_csv(file)
Beispiel #3
0
def main():
    fig, ax = plt.subplots()
    diffs = []
    # Calculate differences for all models
    for file in glob(os.path.join('compensation', 'compensated', '**',
                                  '*.csv'),
                     recursive=True):
        file = os.path.abspath(file)
        comp = FrequencyResponse.read_from_csv(file)
        comp.interpolate()
        comp.center()
        raw_data_path = file.replace('compensated', 'raw')
        raw = FrequencyResponse.read_from_csv(raw_data_path)
        raw.interpolate()
        raw.center()
        diff = FrequencyResponse(name=comp.name,
                                 frequency=comp.frequency,
                                 raw=raw.raw - comp.raw)
        plt.plot(diff.frequency, diff.raw)
        diffs.append(diff.raw)

    # Average and smoothen difference
    f = FrequencyResponse.generate_frequencies()
    diffs = np.vstack(diffs)
    diff = np.mean(diffs, axis=0)
    diff = FrequencyResponse(name='Headphone.com Compensation',
                             frequency=f,
                             raw=diff)
    diff.smoothen_fractional_octave(window_size=1 / 9, iterations=10)
    diff.raw = diff.smoothed
    diff.smoothed = np.array([])

    plt.xlabel('Frequency (Hz)')
    plt.semilogx()
    plt.xlim([20, 20000])
    plt.ylabel('Amplitude (dBr)')
    plt.ylim([-15, 15])
    plt.grid(which='major')
    plt.grid(which='minor')
    plt.title('Headphone.com Compensation Function')
    ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:.0f}'))
    plt.show()

    diff.write_to_csv('headphonecom_compensation.csv')
    diff.plot_graph(show=True,
                    f_min=10,
                    f_max=20000,
                    file_path='headphonecom_compensation.png')
Beispiel #4
0
def main():
    for file in glob('oratory1990/data/*/*/*.csv'):
        fr = FrequencyResponse.read_from_csv(file)
        fr.interpolate()
        fr.center()
        fr.write_to_csv(file)
        print(fr.name)
Beispiel #5
0
def main():
    fs = 48000
    f_res = 5
    input_dir = os.path.join('oratory1990', 'data', 'onear')
    glob_files = glob(os.path.join(input_dir, '**', '*.csv'), recursive=True)
    for input_file_path in glob_files:
        fr = FrequencyResponse.read_from_csv(input_file_path)
        fr.equalization = fr.raw
        fr.raw = np.array([])

        mp = fr.minimum_phase_impulse_response(fs=fs, f_res=f_res)
        f_mp, mp = fft(mp, fs)

        lp = fr.linear_phase_impulse_response(fs=fs, f_res=f_res)
        f_lp, lp = fft(lp, fs)

        plt.plot(f_lp, lp)
        plt.plot(f_mp, mp)
        plt.legend(['Linear phase', 'Minimum phase'])
        plt.semilogx()
        plt.xlabel('Frequency (Hz)')
        plt.xlim([20, 20000])
        plt.ylabel('Gain (dBr)')
        plt.ylim([-40, 0])
        plt.title(fr.name)
        plt.show()
Beispiel #6
0
def main():
    with open('results/README.md', 'r') as f:
        lines = f.read().split('\n')[1:]

    models = []
    rmses = []

    for line in lines:
        # Parse file path
        model = re.search('\[.+\]', line)[0][1:-1]
        url = re.search('\]\(.+\)', line)[0][2:-1]
        path = os.path.abspath(url[52:].replace('%20', ' '))
        specific_model = os.path.split(path)[-1]
        path = os.path.join(path, specific_model + '.csv')
        # Record model and RMSE of frequency response
        fr = FrequencyResponse.read_from_csv(path)
        models.append(model)
        rmses.append(np.sqrt(np.mean(np.square(fr.error))))

    # Sort models by RMSE
    models = np.array(models)
    rmses = np.array(rmses)
    sorted_inds = np.argsort(rmses)
    rmses = rmses[sorted_inds]
    models = models[sorted_inds]

    data = np.transpose(np.vstack((models, rmses)))
    print(data.shape)
    s = '# Hall of Fame\nHeadphones with smallest deviation (RMSE) from ideal frequency target.\n'
    for row in data:
        s += '- {model}: {rmse:.2f}dB\n'.format(model=row[0], rmse=float(row[1]))
    with open('Hall of Fame.md', 'w') as f:
        f.write(s)
Beispiel #7
0
def ranking_row(file_path, target, form='onear'):
    dir_path = os.path.abspath(os.path.join(file_path, os.pardir))
    rel_path = os.path.relpath(dir_path, os.path.join(ROOT_DIR, 'results'))
    url = form_url(rel_path)
    fr = FrequencyResponse.read_from_csv(file_path)
    if re.search(MOD_REGEX, fr.name):
        return None
    fr.interpolate()
    fr.compensate(target, bass_boost_gain=0.0
                  )  # Pre-computed results are with Harman target without bass
    if form == 'onear':
        score, std, slope = fr.harman_onear_preference_score()
        return [
            f'[{fr.name}]({url})', f'{score:.0f}', f'{std:.2f}', f'{slope:.2f}'
        ]
    elif form == 'inear':
        score, std, slope, mean = fr.harman_inear_preference_score()
        return [
            f'[{fr.name}]({url})', f'{score:.0f}', f'{std:.2f}',
            f'{slope:.2f}', f'{mean:.2f}'
        ]
    if '|' in f'[{fr.name}]({url})':
        print(file_path)
        print(fr.name)
        print(f'[{fr.name}]({url})')
Beispiel #8
0
def main():
    models = {}
    for file_path in glob(os.path.join(DIR, '*')):
        model = os.path.split(file_path)[-1]
        if not (re.search(' sample [a-zA-Z0-9]$', model, re.IGNORECASE)
                or re.search(' sn[a-zA-Z0-9]+$', model, re.IGNORECASE)):
            # Skip measurements with sample or serial number, those have averaged results
            continue
        norm = re.sub(' sample [a-zA-Z0-9]$', '', model, 0, re.IGNORECASE)
        norm = re.sub(' sn[a-zA-Z0-9]+$', '', norm, 0, re.IGNORECASE)
        try:
            models[norm].append(model)
        except KeyError as err:
            models[norm] = [model]

    for norm, origs in models.items():
        if len(origs) > 1:
            print(norm, origs)
            avg = np.zeros(613)
            f = FrequencyResponse.generate_frequencies()
            for model in origs:
                fr = FrequencyResponse.read_from_csv(
                    os.path.join(DIR, model, model + '.csv'))
                fr.interpolate()
                fr.center()
                avg += fr.raw
            avg /= len(origs)
            fr = FrequencyResponse(name=norm, frequency=f, raw=avg)
            d = os.path.join(OUT_DIR, norm)
            if not os.path.isdir(d):
                os.makedirs(d)
            fr.write_to_csv(os.path.join(d, norm + '.csv'))
Beispiel #9
0
def average_measurements(input_dir=None, output_dir=None):
    if input_dir is None:
        raise TypeError('Input directory path is required!')
    if output_dir is None:
        output_dir = os.path.abspath(input_dir)
    input_dir = os.path.abspath(input_dir)
    output_dir = os.path.abspath(output_dir)

    models = {}
    for file_path in glob(os.path.join(input_dir, '*')):
        model = os.path.split(file_path)[-1]
        if not re.search(MOD_REGEX, model, re.IGNORECASE):
            continue
        norm = re.sub(MOD_REGEX, '', model, 0, flags=re.IGNORECASE)
        try:
            models[norm].append(model)
        except KeyError as err:
            models[norm] = [model]

    for norm, origs in models.items():
        if len(origs) > 1:
            f = FrequencyResponse.generate_frequencies()
            avg = np.zeros(len(f))
            for model in origs:
                fr = FrequencyResponse.read_from_csv(os.path.join(input_dir, model, model + '.csv'))
                fr.interpolate()
                fr.center()
                avg += fr.raw
            avg /= len(origs)
            fr = FrequencyResponse(name=norm, frequency=f, raw=avg)
            d = os.path.join(output_dir, norm)
            os.makedirs(d, exist_ok=True)
            file_path = os.path.join(d, norm + '.csv')
            fr.write_to_csv(file_path)
Beispiel #10
0
def main():
    trans = FrequencyResponse.read_from_csv('resources\innerfidelity_transformation_SBAF-Serious.csv')
    comp16 = FrequencyResponse.read_from_csv('resources\innerfidelity_compensation_2016.csv')
    comp17 = FrequencyResponse.read_from_csv('resources\innerfidelity_compensation_2017.csv')

    trans.interpolate()
    trans.center()
    comp = FrequencyResponse(name='Serious Compensation', frequency=comp16.frequency, raw=comp16.raw + trans.raw)

    fig, ax = trans.plot_graph(show=False)
    comp16.plot_graph(fig=fig, ax=ax, show=False)
    comp.plot_graph(fig=fig, ax=ax, show=False)
    comp17.plot_graph(fig=fig, ax=ax, show=False)
    fig.legend(['Serious', '2016', '2016+Serious', '2017'])
    plt.show()

    comp.write_to_csv('resources\innerfidelity_compensation_SBAF-Serious.csv')
    comp.plot_graph(file_path='resources\innerfidelity_compensation_SBAF_Serious.png')
def main():
    dt770 = FrequencyResponse.read_from_csv('headphonecom/data/onear/Beyerdynamic DT770/Beyerdynamic DT770.csv')
    dt770.interpolate()
    he400s = FrequencyResponse.read_from_csv('innerfidelity/data/onear/HiFiMAN HE400S/HiFiMAN HE400S.csv')
    he400s.interpolate()
    calibration = FrequencyResponse.read_from_csv('calibration/headphonecom_raw_to_innerfidelity_raw.csv')
    calibration.interpolate()
    compensation = FrequencyResponse.read_from_csv('innerfidelity/resources/innerfidelity_compensation_2017.csv')
    compensation.interpolate()

    dt770_calibrated = FrequencyResponse(name='DT 770 calibrated', frequency=dt770.frequency, raw=dt770.raw)
    dt770_calibrated.calibrate(calibration)
    dt770_calibrated.compensate(he400s)
    #dt770_calibrated.compensate(compensation)
    dt770_calibrated.center()
    dt770_calibrated.smoothen()
    dt770_calibrated.equalize(smoothen=True)
    dt770_calibrated.plot_graph(a_min=-20, a_max=20)
Beispiel #12
0
def main(oe, ie):
    oe18 = FrequencyResponse.read_from_csv(
        'compensation/harman_over-ear_2018.csv')
    oe18wob = FrequencyResponse.read_from_csv(
        'compensation/harman_over-ear_2018_wo_bass.csv')
    ie17 = FrequencyResponse.read_from_csv(
        'compensation/harman_in-ear_2017-1.csv')
    ie17wob = FrequencyResponse.read_from_csv(
        'compensation/harman_in-ear_2017-1_wo_bass.csv')

    if oe:
        bass = FrequencyResponse(name='Bass', frequency=oe18.frequency)
        bass.raw = bass._sigmoid(35, 280, 4, -2.0)
        fig, ax = oe18.plot_graph(show=False, color=None)
        oe18wob.plot_graph(fig=fig, ax=ax, show=False, color=None)
        bass.plot_graph(fig=fig, ax=ax, show=False, color=None)
        boost = FrequencyResponse(name='Boost',
                                  frequency=bass.frequency,
                                  raw=bass.raw)
        boost.center()
        oe18wob_boosted = FrequencyResponse(name='Boosted OE18',
                                            frequency=oe18.frequency,
                                            raw=oe18wob.raw + boost.raw)
        oe18wob_boosted.plot_graph(fig=fig, ax=ax, show=False, color=None)
        ax.legend(['OE18', 'OE18 w/o bass', 'Bass', 'Boosted'])
        plt.show()

    if ie:
        bass = FrequencyResponse(name='Bass', frequency=ie17.frequency)
        bass.raw = bass._sigmoid(25, 350, 8, -1.7)
        fig, ax = ie17.plot_graph(show=False, color=None)
        ie17wob.plot_graph(fig=fig, ax=ax, show=False, color=None)
        bass.plot_graph(fig=fig, ax=ax, show=False, color=None)
        boost = FrequencyResponse(name='Boost',
                                  frequency=bass.frequency,
                                  raw=bass.raw)
        boost.center()
        ie17wob_boosted = FrequencyResponse(name='Boosted IE17',
                                            frequency=ie17.frequency,
                                            raw=ie17wob.raw + boost.raw)
        ie17wob_boosted.plot_graph(fig=fig, ax=ax, show=False, color=None)
        ax.legend(['IE17', 'IE17 w/o bass', 'Bass', 'Boosted'])
        plt.show()
Beispiel #13
0
def main():
    paths = list(
        glob(os.path.join(ROOT_DIR, 'measurements', '**', '*.csv'),
             recursive=True))
    paths += list(
        glob(os.path.join(ROOT_DIR, 'compensation', '*.csv'), recursive=True))
    for file_path in paths:
        fr = FrequencyResponse.read_from_csv(file_path)
        fr.interpolate()
        fr.write_to_csv(file_path)
Beispiel #14
0
def main():
    serious = FrequencyResponse.read_from_csv('resources/rtings_compensation_sbaf-serious.csv')
    native = FrequencyResponse.read_from_csv('resources/rtings_compensation.csv')
    avg = measurements_avg()
    hd650 = FrequencyResponse.read_from_csv('data/onear/Sennheiser HD 650/Sennheiser HD 650.csv')

    fig, ax = native.plot_graph(show=False, color=None)
    serious.plot_graph(fig=fig, ax=ax, show=False, color=None)
    avg.plot_graph(fig=fig, ax=ax, show=False, color=None)
    hd650.plot_graph(fig=fig, ax=ax, show=False, color=None)

    plt.legend(['Rtings native', 'SBAF Serious', 'Measurements Avg', 'Sennheiser HD 650'])
    plt.title('Rtings Targets')
    plt.ylim([-10.0, 12.0])
    plt.show()
    fig.savefig('resources/rtings_targets_comparison.png', dpi=120)

    avg.raw[avg.frequency < 2500] = native.raw[native.frequency < 2500]
    avg.write_to_csv('resources/rtings_compensation_avg.csv')
    avg.plot_graph(show=False, file_path='resources/rtings_compensation_avg.png', color=None)
Beispiel #15
0
def main():
    ht18 = FrequencyResponse.read_from_csv(
        'compensation/harman_over-ear_2018_wo_bass.csv')
    df = FrequencyResponse.read_from_csv('compensation/diffuse_field.csv')
    df.raw += df._tilt(-1)
    eht = ht18.copy()
    eht.raw -= df.raw

    ifss = FrequencyResponse.read_from_csv(
        'innerfidelity/resources/innerfidelity_compensation_sbaf-serious.csv')
    #ifdf = FrequencyResponse.read_from_csv('innerfidelity/resources/innerfidelity_compensation_2016.csv')
    ifdf = FrequencyResponse.read_from_csv(
        'headphonecom/resources/headphonecom_compensation.csv')
    ifdf.raw += df._tilt(-1)
    #ifdf.raw -= 2.5
    eif = ifss.copy()
    eif.raw -= ifdf.raw

    fig, axs = plt.subplots(1, 2)
    fig.set_size_inches(18, 9)

    ht18.plot_graph(fig=fig, ax=axs[0], show=False, color='blue')
    df.plot_graph(fig=fig, ax=axs[0], show=False, color='orange')
    eht.plot_graph(fig=fig, ax=axs[0], show=False, color='red')
    axs[0].legend(
        ['Harman target 2018', 'Diffuse field (-1 dB/oct)', 'Difference'])
    axs[0].set_title('Harman target vs Diffuse field')

    ifss.plot_graph(fig=fig, ax=axs[1], show=False, color='blue')
    ifdf.plot_graph(fig=fig, ax=axs[1], show=False, color='orange')
    eif.plot_graph(fig=fig, ax=axs[1], show=False, color='red')
    #axs[1].legend(['SBAF-Serious', 'Innerfidelity diffuse field (-1 dB/oct)', 'Difference'])
    axs[1].legend(
        ['SBAF-Serious', 'Headphonecom target (-1 dB/oct)', 'Difference'])
    axs[1].set_title('Innerfidelity SBAF-Serious vs Headphonecom')

    plt.show()
Beispiel #16
0
def main():
    fs = 48000
    f_res = 60
    input_dir = os.path.join('oratory1990', 'data', 'onear')
    glob_files = glob(os.path.join(input_dir, '**', '*.csv'), recursive=True)
    for input_file_path in glob_files:
        fr = FrequencyResponse.read_from_csv(input_file_path)
        fr.equalization = fr.raw
        fr.raw = np.array([])

        mp = fr.minimum_phase_impulse_response(fs=fs, f_res=f_res, normalize=False)
        mp = np.concatenate([mp, np.zeros(fs//10 - len(mp))])
        f_mp, mp = fft(mp, fs)
        f_mp[0] = 0.1
        mp = FrequencyResponse(name='Minimum phase', frequency=f_mp, raw=mp)
        mp.center()

        lp = fr.linear_phase_impulse_response(fs=fs, f_res=f_res, normalize=False)
        lp = np.concatenate([lp, np.zeros(fs//10 - len(lp))])
        f_lp, lp = fft(lp, fs)
        f_lp[0] = 0.1
        lp = FrequencyResponse(name='Linear phase', frequency=f_lp, raw=lp)
        lp.center()

        fig, ax = plt.subplots()
        fig.set_size_inches(15, 10)
        plt.plot(fr.frequency, fr.equalization)
        plt.plot(mp.frequency, mp.raw, '.-')
        plt.plot(lp.frequency, lp.raw, '.-')
        plt.legend(['Raw', 'Minimum phase', 'Linear phase'])
        plt.semilogx()
        plt.xlabel('Frequency (Hz)')
        plt.xlim([1, 20000])
        plt.ylabel('Gain (dBr)')
        plt.ylim([-20, 20])
        plt.title(fr.name)
        plt.grid(True, which='major')
        plt.grid(True, which='minor')
        plt.show()
Beispiel #17
0
def main(input_dir=None, output_dir=None):
    if input_dir is None:
        raise TypeError('Input directory path is required!')
    if output_dir is None:
        raise TypeError('Output directory path is required!')
    input_dir = os.path.abspath(input_dir)
    output_dir = os.path.abspath(output_dir)

    models = {}
    for file_path in glob(os.path.join(input_dir, '*')):
        model = os.path.split(file_path)[-1]
        if not (re.search(' sample [a-zA-Z0-9]$', model, re.IGNORECASE)
                or re.search(' sn[a-zA-Z0-9]+$', model, re.IGNORECASE)):
            continue
        norm = re.sub(' sample [a-zA-Z0-9]$', '', model, 0, re.IGNORECASE)
        norm = re.sub(' sn[a-zA-Z0-9]+$', '', norm, 0, re.IGNORECASE)
        try:
            models[norm].append(model)
        except KeyError as err:
            models[norm] = [model]

    for norm, origs in models.items():
        if len(origs) > 1:
            print(norm, origs)
            avg = np.zeros(613)
            f = FrequencyResponse.generate_frequencies()
            for model in origs:
                fr = FrequencyResponse.read_from_csv(
                    os.path.join(input_dir, model, model + '.csv'))
                fr.interpolate()
                fr.center()
                avg += fr.raw
            avg /= len(origs)
            fr = FrequencyResponse(name=norm, frequency=f, raw=avg)
            d = os.path.join(output_dir, norm)
            if not os.path.isdir(d):
                os.makedirs(d)
            fr.write_to_csv(os.path.join(d, norm + '.csv'))
Beispiel #18
0
def main():
    oe18 = FrequencyResponse.read_from_csv(
        'compensation/harman_over-ear_2018.csv')
    oe18_nobass = FrequencyResponse.read_from_csv(
        'compensation/harman_over-ear_2018_wo_bass.csv')
    oe18_bass = oe18_nobass.copy()
    oe18_bass.raw += digital_coeffs(oe18_bass.frequency, 48000,
                                    *low_shelf(100, 0.65, 6, 48000))

    iem19 = FrequencyResponse.read_from_csv(
        'compensation/harman_in-ear_2019v2.csv')
    iem19_nobass = FrequencyResponse.read_from_csv(
        'compensation/harman_in-ear_2019v2_wo_bass.csv')
    iem19_bass = iem19_nobass.copy()
    iem19_bass.raw += digital_coeffs(iem19_bass.frequency, 48000,
                                     *low_shelf(100, 0.65, 9.5, 48000))

    usound = FrequencyResponse.read_from_csv('compensation/usound.csv')
    usound_nobass = FrequencyResponse.read_from_csv(
        'compensation/usound_wo_bass.csv')
    usound_bass = usound_nobass.copy()
    usound_bass.raw += digital_coeffs(usound_bass.frequency, 48000,
                                      *low_shelf(150, 0.65, 9.4, 48000))

    fig, ax = oe18.plot_graph(show=False, color='C0')
    oe18_nobass.plot_graph(show=False, color='C1', fig=fig, ax=ax)
    oe18_bass.plot_graph(show=False, color='C2', fig=fig, ax=ax)
    ax.legend(['Original', 'Without bass', 'Shelf bass'])

    fig, ax = iem19.plot_graph(show=False, color='C0')
    iem19_nobass.plot_graph(show=False, color='C1', fig=fig, ax=ax)
    iem19_bass.plot_graph(show=False, color='C2', fig=fig, ax=ax)
    ax.legend(['Original', 'Without bass', 'Shelf bass'])

    fig, ax = usound.plot_graph(show=False, color='C0')
    usound_nobass.plot_graph(show=False, color='C1', fig=fig, ax=ax)
    usound_bass.plot_graph(show=False, color='C2', fig=fig, ax=ax)
    ax.legend(['Original', 'Without bass', 'Shelf bass'])

    plt.show()
Beispiel #19
0
def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--input_dir',
                            type=str,
                            default='images',
                            help='Path to images directory.')
    arg_parser.add_argument('--inspection_dir',
                            type=str,
                            default='inspection',
                            help='Path to inspection directory.')
    arg_parser.add_argument('--output_dir',
                            type=str,
                            default='data',
                            help='Path to data directory.')
    arg_parser.add_argument('--compensation',
                            type=str,
                            default='resources/rtings_compensation_w_bass.csv',
                            help='Path to compensation file.')
    cli_args = arg_parser.parse_args()

    input_dir = os.path.abspath(cli_args.input_dir)
    inspection_dir = os.path.abspath(cli_args.inspection_dir)
    output_dir = os.path.abspath(cli_args.output_dir)
    compensation_path = os.path.abspath(cli_args.compensation)

    if not os.path.isdir(inspection_dir):
        os.makedirs(inspection_dir)
    if not os.path.isdir(os.path.join(inspection_dir, 'left')):
        os.makedirs(os.path.join(inspection_dir, 'left'))
    if not os.path.isdir(os.path.join(inspection_dir, 'right')):
        os.makedirs(os.path.join(inspection_dir, 'right'))
    if not os.path.isdir(os.path.join(inspection_dir, 'fr')):
        os.makedirs(os.path.join(inspection_dir, 'fr'))
    if not os.path.isdir(output_dir):
        os.makedirs(output_dir)

    # Compensation
    comp = FrequencyResponse.read_from_csv(compensation_path)

    for file_path in glob(os.path.join(input_dir, '*.png')):
        print(file_path)
        name = os.path.split(file_path)[-1].replace('.png', '')

        # Read and parse image
        im = Image.open(file_path)
        fr_left, inspection_left = parse_image(im, name, 'left')
        fr_right, inspection_right = parse_image(im, name, 'right')

        # Save inspection images
        inspection_left.save(
            os.path.join(inspection_dir, 'left', name + '.png'))
        inspection_right.save(
            os.path.join(inspection_dir, 'right', name + '.png'))

        # Create directory
        dir_path = os.path.join(output_dir, name)
        if not os.path.isdir(dir_path):
            os.makedirs(dir_path)

        # Average channels
        if not np.array_equal(fr_left.frequency, fr_right.frequency):
            warnings.warn(
                'Left and right channel frequency data of "{}" don\'t match!'.
                format(name))
            continue
        raw = np.mean(np.vstack(
            (fr_left.raw, fr_right.raw)), axis=0) + comp.raw
        fr = FrequencyResponse(name=name, frequency=fr_left.frequency, raw=raw)
        fr.plot_graph(show=False,
                      file_path=os.path.join(inspection_dir, 'fr',
                                             name + '.png'))

        # Write to CSV
        fr.write_to_csv(os.path.join(output_dir, name, name + '.csv'))
Beispiel #20
0
def main():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--input_dir',
                            type=str,
                            default=os.path.join(DIR_PATH, 'raw_data'),
                            help='Path to raw data directory.')
    arg_parser.add_argument('--inspection_dir',
                            type=str,
                            default=os.path.join(DIR_PATH, 'inspection'),
                            help='Path to inspection directory.')
    arg_parser.add_argument('--output_dir',
                            type=str,
                            default=os.path.join(DIR_PATH, 'data'),
                            help='Path to data directory.')
    arg_parser.add_argument('--name_index',
                            type=str,
                            default=os.path.join(DIR_PATH, 'name_index.tsv'),
                            help='Path to name index TSV file.')
    cli_args = arg_parser.parse_args()

    input_dir = os.path.abspath(cli_args.input_dir)
    inspection_dir = os.path.abspath(cli_args.inspection_dir)
    output_dir = os.path.abspath(cli_args.output_dir)
    name_index = os.path.abspath(cli_args.name_index)

    if not os.path.isdir(inspection_dir):
        os.makedirs(inspection_dir)
    if not os.path.isdir(output_dir):
        os.makedirs(output_dir)

    # Compensation
    onear_target = FrequencyResponse.read_from_csv(
        os.path.join(DIR_PATH, 'resources', 'rtings_compensation_w_bass.csv'))
    inear_target = FrequencyResponse.read_from_csv(
        os.path.join(DIR_PATH, 'resources',
                     'rtings_inear_compensation_w_bass.csv'))

    df = pd.read_csv(name_index, sep='\t', header=0)
    df = df.fillna('')
    name_index = dict()
    for index, row in df.iterrows():
        name_index[row['name']] = row

    for file_path in glob(os.path.join(input_dir, '*.json')):
        name = os.path.split(file_path)[-1].replace('.json', '')
        if name not in name_index:
            warnings.warn('{} not in name index, skipping'.format(name))
            continue
        if name_index[name]['type'] not in ['onear', 'inear', 'earbud']:
            warnings.warn('Incorrect type "{t}" for "{hp}"'.format(
                t=name_index[name]['type'], hp=name))
            continue
        hp_type = name_index[name]['type']
        if name_index[name]['full_name']:
            name = name_index[name]['full_name']

        # Read and parse image
        with open(file_path) as f:
            json_data = json.loads(f.read())
        fr, target = parse_json(json_data, name)
        fr.interpolate()
        if np.std(fr.raw) == 0:
            # Frequency response data has non-zero target response, use that
            target.interpolate()
            target = target
            print('Using target for', name)
        elif hp_type == 'inear':
            # Using in-ear target response
            target = inear_target
        else:
            # Using on-ear or earbud target response
            target = onear_target
        target.center()
        fr.raw += target.raw
        fr.center()

        # Save inspection images
        fr.plot_graph(show=False,
                      close=True,
                      file_path=os.path.join(inspection_dir, name + '.png'))

        # Create directory
        dir_path = os.path.join(output_dir, hp_type, name)
        if not os.path.isdir(dir_path):
            os.makedirs(dir_path)

        # Write to CSV
        hp_file_path = os.path.join(dir_path, name + '.csv')
        fr.write_to_csv(hp_file_path)
        print('Saved "{hp}" to "{path}"'.format(hp=name, path=hp_file_path))
Beispiel #21
0
import os
import sys
import requests
import json
import numpy as np
from bs4 import BeautifulSoup
sys.path.insert(1, os.path.realpath(os.path.join(sys.path[0], os.pardir, os.pardir)))
from measurements.name_index import NameIndex
from measurements.crawler import Crawler
from frequency_response import FrequencyResponse

DIR_PATH = os.path.abspath(os.path.join(__file__, os.pardir))

# Compensation
ONEAR_TARGET = FrequencyResponse.read_from_csv(
    os.path.join(DIR_PATH, 'resources', 'rtings_compensation_w_bass.csv')
)
INEAR_TARGET = FrequencyResponse.read_from_csv(
    os.path.join(DIR_PATH, 'resources', 'rtings_inear_compensation_w_bass.csv')
)


class RtingsCrawler(Crawler):
    @staticmethod
    def read_name_index():
        return NameIndex.read_tsv(os.path.join(DIR_PATH, 'name_index.tsv'))

    def write_name_index(self):
        self.name_index.write_tsv(os.path.join(DIR_PATH, 'name_index.tsv'))

    @staticmethod
Beispiel #22
0
def main():
    harman_onear = FrequencyResponse.read_from_csv(
        os.path.join(ROOT_DIR, 'compensation', 'harman_over-ear_2018.csv'))
    harman_onear_wo_bass = FrequencyResponse.read_from_csv(
        os.path.join(ROOT_DIR, 'compensation',
                     'harman_over-ear_2018_wo_bass.csv'))
    harman_inear = FrequencyResponse.read_from_csv(
        os.path.join(ROOT_DIR, 'compensation', 'harman_in-ear_2019v2.csv'))
    harman_inear_wo_bass = FrequencyResponse.read_from_csv(
        os.path.join(ROOT_DIR, 'compensation',
                     'harman_in-ear_2019v2_wo_bass.csv'))

    oratory1990_onear = get_measurements(
        os.path.join(MEASUREMENTS, 'oratory1990', 'data', 'onear'))
    oratory1990_inear = get_measurements(
        os.path.join(MEASUREMENTS, 'oratory1990', 'data', 'inear'))

    crinacle_inear = get_measurements(
        os.path.join(MEASUREMENTS, 'crinacle', 'data', 'inear'))
    inear_ref = oratory1990_inear.copy()
    inear_names = [fr.name for fr in inear_ref]
    for fr in crinacle_inear:
        if fr.name not in inear_names:
            inear_ref.append(fr)

    dbs = [
        ('crinacle_harman_in-ear_2019v2_wo_bass', crinacle_inear,
         oratory1990_inear, None),
        ('crinacle_ears-711_harman_over-ear_2018_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'crinacle', 'data', 'onear',
                          'Ears-711')), oratory1990_onear, None),
        ('headphonecom_harman_over-ear_2018_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'headphonecom', 'data',
                          'onear')), oratory1990_onear,
         FrequencyResponse.read_from_csv(
             os.path.join(MEASUREMENTS, 'headphonecom', 'resources',
                          'headphonecom_compensation_sbaf-serious.csv'))),
        ('headphonecom_harman_in-ear_2019v2_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'headphonecom', 'data',
                          'inear')), inear_ref,
         FrequencyResponse.read_from_csv(
             os.path.join(MEASUREMENTS, 'headphonecom', 'resources',
                          'headphonecom_compensation_sbaf-serious.csv'))),
        ('innerfidelity_harman_over-ear_2018_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'innerfidelity', 'data',
                          'onear')), oratory1990_onear,
         FrequencyResponse.read_from_csv(
             os.path.join(MEASUREMENTS, 'innerfidelity', 'resources',
                          'innerfidelity_compensation_sbaf-serious.csv'))),
        ('innerfidelity_harman_in-ear_2019v2_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'innerfidelity', 'data',
                          'inear')), inear_ref,
         FrequencyResponse.read_from_csv(
             os.path.join(MEASUREMENTS, 'innerfidelity', 'resources',
                          'innerfidelity_compensation_sbaf-serious.csv'))),
        ('referenceaudioanalyzer_hdm-x_harman_over-ear_2018_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'referenceaudioanalyzer', 'data',
                          'onear', 'HDM-X')), oratory1990_onear, None),
        ('referenceaudioanalyzer_hdm1_harman_over-ear_2018_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'referenceaudioanalyzer', 'data',
                          'onear', 'HDM1')), oratory1990_onear, None),
        ('referenceaudioanalyzer_siec_harman_in-ear_2019v2_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'referenceaudioanalyzer', 'data',
                          'inear', 'SIEC')), inear_ref, None),
        ('rtings_harman_over-ear_2018_wo_bass',
         get_measurements(os.path.join(MEASUREMENTS, 'rtings', 'data',
                                       'onear')), oratory1990_onear,
         FrequencyResponse.read_from_csv(
             os.path.join(MEASUREMENTS, 'rtings', 'resources',
                          'rtings_compensation_avg.csv'))),
        ('rtings_harman_in-ear_2019v2_wo_bass',
         get_measurements(os.path.join(MEASUREMENTS, 'rtings', 'data',
                                       'inear')), inear_ref,
         FrequencyResponse.read_from_csv(
             os.path.join(MEASUREMENTS, 'rtings', 'resources',
                          'rtings_compensation_avg.csv'))),
        ('crinacle_gras_43ag-7_harman_over-ear_2018_wo_bass',
         get_measurements(
             os.path.join(MEASUREMENTS, 'crinacle', 'data', 'onear',
                          'GRAS 43AG-7')), oratory1990_onear, None)
    ]

    stds = []
    for name, measurements, ref, original_target in dbs:
        print(f'Calibrating {name}...')
        # Find matching pairs
        pairs = []
        for fr in measurements:
            for candidate in ref:
                if fr.name.lower() == candidate.name.lower():
                    pairs.append((fr, candidate))

        fig, axs = plt.subplots(1, 3)
        fig.set_size_inches(30, 8)
        fig.suptitle(name)
        description = 'Calibrated against reference measurements with headphones: '
        line_len = len(description)
        for fr, _ in pairs:
            if line_len > 240:
                description += '\n'
                line_len = 0
            description += f'{fr.name}, '
            line_len += len(fr.name) + 2
        description = description[:-2]
        fig.text(0.5, -0.05, description, ha='center')

        # Individual errors
        errors = []
        i = 0
        for fr, target in pairs:
            fr.compensate(target, min_mean_error=True)
            errors.append(fr.error)
            fr.raw = fr.error.copy()
            fr.error = []
            fr.target = []
            fr.plot_graph(fig=fig,
                          ax=axs[0],
                          show=False,
                          raw_plot_kwargs={
                              'color': 'C0',
                              'alpha': 0.3
                          })
            i += 1
        axs[0].set_ylim([-15, 15])
        axs[0].set_title('Individual Errors')
        axs[0].legend(['Error'])

        # Mean and standard deviation
        errors = np.vstack(errors)
        mean = np.mean(errors, axis=0)
        std = np.std(errors, axis=0)
        stds.append(FrequencyResponse(name=name, raw=std))
        fr = FrequencyResponse(name='Mean and Standard Deviation')
        fr.raw = mean
        fr.smoothen_fractional_octave(window_size=1 / 3,
                                      treble_window_size=1 / 3)
        fr.raw = fr.smoothed.copy()
        fr.smoothed = []
        fr.plot_graph(fig=fig, ax=axs[1], color='C0', show=False)
        axs[1].fill_between(fr.frequency,
                            mean - std,
                            mean + std,
                            facecolor='#c1dff5')
        axs[1].set_ylim([-15, 15])
        axs[1].legend(['Mean', 'STD'])

        # Target curves
        ref_target = harman_onear_wo_bass if 'over-ear' in name else harman_inear_wo_bass
        ref_target.plot_graph(fig=fig, ax=axs[2], show=False, color='C0')
        target = ref_target.copy()
        target.name = name
        target.raw += fr.raw
        target.plot_graph(fig=fig, ax=axs[2], show=False, color='C1')
        if original_target is not None:
            original_target.plot_graph(fig=fig,
                                       ax=axs[2],
                                       show=False,
                                       color='C2')
            axs[2].legend([ref_target.name, target.name, original_target.name])
        else:
            axs[2].legend([ref_target.name, target.name])
        axs[2].set_title(f'{name} target')
        axs[2].set_ylim([-15, 15])

        fig.savefig(os.path.join(DIR_PATH, f'calibration_{name}.png'),
                    bbox_inches='tight')

        target.plot_graph(show=False,
                          file_path=os.path.join(DIR_PATH, f'{name}.png'),
                          color='C0')
        target.write_to_csv(file_path=os.path.join(DIR_PATH, f'{name}.csv'))
        plt.close(fig)

    fig, axs = plt.subplots(1, 2)
    fig.set_size_inches(20, 8)
    onear_labels = []
    inear_labels = []
    for fr in stds:
        if 'over-ear' in fr.name:
            fr.plot_graph(fig=fig,
                          ax=axs[0],
                          color=f'C{len(onear_labels)}',
                          show=False)
            onear_labels.append(fr.name)
        else:
            fr.plot_graph(fig=fig,
                          ax=axs[1],
                          color=f'C{len(inear_labels)}',
                          show=False)
            inear_labels.append(fr.name)
    axs[0].legend(onear_labels)
    axs[1].legend(inear_labels)
    axs[0].set_title('On-ear')
    axs[1].set_title('In-ear')
    axs[0].set_ylim([0, 8])
    axs[1].set_ylim([0, 8])
    fig.savefig(os.path.join(DIR_PATH, 'STDs.png'))
    plt.close(fig)
Beispiel #23
0
def main():
    harman_nobass = FrequencyResponse.read_from_csv(
        os.path.join(DIR_PATH, os.pardir, os.pardir, 'compensation',
                     'harman_over-ear_2018_wo_bass.csv'))
    harman = FrequencyResponse.read_from_csv(
        os.path.join(DIR_PATH, os.pardir, os.pardir, 'compensation',
                     'harman_over-ear_2018.csv'))
    oratory1990 = measurements(
        os.path.join(DIR_PATH, os.pardir, 'oratory1990', 'data', 'onear'))
    crinacle = measurements(os.path.join(DIR_PATH, 'data', 'onear'))
    pairs = []
    for fr in crinacle:
        for candidate in oratory1990:
            if fr.name.lower() == candidate.name.lower():
                pairs.append((fr, candidate))

    fig, axs = plt.subplots(1, 3)
    fig.set_size_inches(25, 10)
    fig.suptitle('Crinacle Over-ear Calibration')
    description = 'Calibrated against oratory1990 measurements with headphones: '
    line_len = len(description)
    for fr, _ in pairs:
        if line_len > 240:
            description += '\n'
            line_len = 0
        description += f'{fr.name}, '
        line_len += len(fr.name) + 2
    description = description[:-2]
    fig.text(0.5, 0.93, description, ha='center')

    errors = []
    i = 0
    for fr, target in pairs:
        fr.compensate(target, min_mean_error=True)
        errors.append(fr.error)
        fr.raw = fr.error.copy()
        fr.error = []
        fr.target = []
        fr.plot_graph(fig=fig, ax=axs[0], show=False, color=f'C{i}')
        i += 1
    axs[0].set_ylim([-15, 15])
    axs[0].set_title('Individual Errors')
    errors = np.vstack(errors)
    mean = np.mean(errors, axis=0)
    std = np.std(errors, axis=0)

    fr = FrequencyResponse(name='Mean and Standard Deviation')
    fr.raw = mean
    fr.smoothen_heavy_light()
    fr.raw = fr.smoothed.copy()
    fr.smoothed = []
    fr.plot_graph(fig=fig, ax=axs[1], color='C0', show=False)
    axs[1].fill_between(fr.frequency,
                        mean - std,
                        mean + std,
                        facecolor='#c1dff5')
    axs[1].set_ylim([-15, 15])

    harman_nobass.plot_graph(fig=fig, ax=axs[2], show=False, color='C0')
    crinacle_bass = harman.copy()
    crinacle_bass.raw += fr.raw
    crinacle_nobass = harman_nobass.copy()
    crinacle_nobass.raw += fr.raw
    crinacle_nobass.plot_graph(fig=fig, ax=axs[2], show=False, color='C1')
    axs[2].legend(
        ['Harman over-ear 2018 w/o bass', 'Crinacle over-ear w/o bass'])
    axs[2].set_title('Crinacle Over-ear Target')
    axs[2].set_ylim([-15, 15])

    resources_dir = os.path.join(DIR_PATH, 'resources')
    os.makedirs(resources_dir, exist_ok=True)
    fig.savefig(os.path.join(DIR_PATH, 'resources', 'calibration.png'),
                bbox_inches='tight')

    crinacle_bass.name = 'Crinacle Over-ear Target with Harman Bass Boost'
    crinacle_bass.plot_graph(show=False,
                             file_path=os.path.join(
                                 resources_dir, 'crinacle_over-ear_bass.png'),
                             color='C0')
    crinacle_bass.write_to_csv(
        file_path=os.path.join(resources_dir, 'crinacle_over-ear_bass.csv'))

    crinacle_nobass.name = 'Crinacle Over-ear Target'
    crinacle_nobass.plot_graph(show=False,
                               file_path=os.path.join(resources_dir,
                                                      'crinacle_over-ear.png'),
                               color='C0')
    crinacle_nobass.write_to_csv(
        file_path=os.path.join(resources_dir, 'crinacle_over-ear.csv'))
Beispiel #24
0
def measurements(dir_path):
    frs = []
    for fp in glob(os.path.join(dir_path, '*', '*.csv')):
        frs.append(FrequencyResponse.read_from_csv(fp))
    return frs
Beispiel #25
0
def measurements_avg():
    stack = []
    for file in glob('data/*/*/*.csv'):
        stack.append(FrequencyResponse.read_from_csv(file).raw)
    return FrequencyResponse(name='AVG', raw=np.mean(np.vstack(stack), axis=0))
Beispiel #26
0
def batch_processing(input_dir=None,
                     output_dir=None,
                     new_only=False,
                     standardize_input=False,
                     compensation=None,
                     equalize=False,
                     parametric_eq=False,
                     fixed_band_eq=False,
                     rockbox=False,
                     fc=None,
                     q=None,
                     ten_band_eq=False,
                     max_filters=None,
                     convolution_eq=False,
                     fs=DEFAULT_FS,
                     bit_depth=DEFAULT_BIT_DEPTH,
                     phase=DEFAULT_PHASE,
                     f_res=DEFAULT_F_RES,
                     bass_boost_gain=DEFAULT_BASS_BOOST_GAIN,
                     bass_boost_fc=DEFAULT_BASS_BOOST_FC,
                     bass_boost_q=DEFAULT_BASS_BOOST_Q,
                     tilt=None,
                     sound_signature=None,
                     max_gain=DEFAULT_MAX_GAIN,
                     treble_f_lower=DEFAULT_TREBLE_F_LOWER,
                     treble_f_upper=DEFAULT_TREBLE_F_UPPER,
                     treble_max_gain=DEFAULT_TREBLE_MAX_GAIN,
                     treble_gain_k=DEFAULT_TREBLE_GAIN_K,
                     show_plot=False):
    """Parses files in input directory and produces equalization results in output directory."""
    start_time = time()

    if convolution_eq and not equalize:
        raise ValueError('equalize must be True when convolution_eq is True.')

    # Dir paths to absolute
    input_dir = os.path.abspath(input_dir)
    glob_files = glob(os.path.join(input_dir, '**', '*.csv'), recursive=True)
    if len(glob_files) == 0:
        raise FileNotFoundError('No CSV files found in "{}"'.format(input_dir))

    if compensation:
        # Creates FrequencyResponse for compensation data
        compensation_path = os.path.abspath(compensation)
        compensation = FrequencyResponse.read_from_csv(compensation_path)
        compensation.interpolate()
        compensation.center()

    if bit_depth == 16:
        bit_depth = "PCM_16"
    elif bit_depth == 24:
        bit_depth = "PCM_24"
    elif bit_depth == 32:
        bit_depth = "PCM_32"
    else:
        raise ValueError('Invalid bit depth. Accepted values are 16, 24 e 32.')

    if sound_signature is not None:
        sound_signature = FrequencyResponse.read_from_csv(sound_signature)
        if len(sound_signature.error) > 0:
            # Error data present, replace raw data with it
            sound_signature.raw = sound_signature.error
        sound_signature.interpolate()
        sound_signature.center()

    # Add files
    n_total = 0
    file_paths = []
    for input_file_path in glob_files:
        relative_path = os.path.relpath(input_file_path, input_dir)
        output_file_path = os.path.join(output_dir,
                                        relative_path) if output_dir else None
        output_file_dir = os.path.split(output_file_path)[0]
        if not new_only or not os.path.isdir(output_file_dir) or not len(
                os.listdir(output_file_dir)):
            # Not looking for only new ones or the output directory doesn't exist or it's empty
            file_paths.append((input_file_path, output_file_path))
            n_total += 1

    n = 0
    for input_file_path, output_file_path in file_paths:
        # Read data from input file
        fr = FrequencyResponse.read_from_csv(input_file_path)

        if standardize_input:
            # Overwrite input data in standard sampling and bias
            fr.interpolate()
            fr.center()
            fr.write_to_csv(input_file_path)

        # Process and equalize
        peq_filters, n_peq_filters, peq_max_gains, fbeq_filters, n_fbeq_filters, fbeq_max_gain = fr.process(
            compensation=compensation,
            min_mean_error=True,
            equalize=equalize,
            parametric_eq=parametric_eq,
            fixed_band_eq=fixed_band_eq,
            fc=fc,
            q=q,
            ten_band_eq=ten_band_eq,
            max_filters=max_filters,
            bass_boost_gain=bass_boost_gain,
            bass_boost_fc=bass_boost_fc,
            bass_boost_q=bass_boost_q,
            tilt=tilt,
            sound_signature=sound_signature,
            max_gain=max_gain,
            treble_f_lower=treble_f_lower,
            treble_f_upper=treble_f_upper,
            treble_max_gain=treble_max_gain,
            treble_gain_k=treble_gain_k,
            fs=fs[0] if type(fs) == list else fs)

        if output_file_path is not None:
            # Copy relative path to output directory
            output_dir_path, _ = os.path.split(output_file_path)
            os.makedirs(output_dir_path, exist_ok=True)

            if equalize:
                # Write EqualizerAPO GraphicEq settings to file
                fr.write_eqapo_graphic_eq(output_file_path.replace(
                    '.csv', ' GraphicEQ.txt'),
                                          normalize=True)
                if parametric_eq:
                    # Write ParametricEq settings to file
                    fr.write_eqapo_parametric_eq(
                        output_file_path.replace('.csv', ' ParametricEQ.txt'),
                        peq_filters,
                        preamp=-(peq_max_gains[-1] + PREAMP_HEADROOM))

                # Write fixed band eq
                if fixed_band_eq or ten_band_eq:
                    # Write fixed band eq settings to file
                    fr.write_eqapo_parametric_eq(
                        output_file_path.replace('.csv', ' FixedBandEQ.txt'),
                        fbeq_filters,
                        preamp=-(fbeq_max_gain + PREAMP_HEADROOM))

                # Write 10 band fixed band eq to Rockbox .cfg file
                if rockbox and ten_band_eq:
                    # Write fixed band eq settings to file
                    fr.write_rockbox_10_band_fixed_eq(
                        output_file_path.replace('.csv', ' RockboxEQ.cfg'),
                        fbeq_filters,
                        preamp=-(fbeq_max_gain + PREAMP_HEADROOM))

                # Write impulse response as WAV
                if convolution_eq:
                    for _fs in fs:
                        if phase in ['linear', 'both']:
                            # Write linear phase impulse response
                            linear_phase_ir = fr.linear_phase_impulse_response(
                                fs=_fs, f_res=f_res, normalize=True)
                            linear_phase_ir = np.tile(linear_phase_ir,
                                                      (2, 1)).T
                            sf.write(
                                output_file_path.replace(
                                    '.csv',
                                    ' linear phase {}Hz.wav'.format(_fs)),
                                linear_phase_ir, _fs, bit_depth)
                        if phase in ['minimum', 'both']:
                            # Write minimum phase impulse response
                            minimum_phase_ir = fr.minimum_phase_impulse_response(
                                fs=_fs, f_res=f_res, normalize=True)
                            minimum_phase_ir = np.tile(minimum_phase_ir,
                                                       (2, 1)).T
                            sf.write(
                                output_file_path.replace(
                                    '.csv',
                                    ' minimum phase {}Hz.wav'.format(_fs)),
                                minimum_phase_ir, _fs, bit_depth)

            # Write results to CSV file
            fr.write_to_csv(output_file_path)

            # Write plots to file and optionally display them
            fr.plot_graph(
                show=show_plot,
                close=not show_plot,
                file_path=output_file_path.replace('.csv', '.png'),
            )

            # Write README.md
            _readme_path = os.path.join(output_dir_path, 'README.md')
            fr.write_readme(_readme_path,
                            max_filters=n_peq_filters,
                            max_gains=peq_max_gains)

        elif show_plot:
            fr.plot_graph(show=True, close=False)

        n += 1
        print(
            f'{n}/{n_total} ({n / n_total * 100:.1f}%) {time() - start_time:.0f}s: {fr.name}'
        )
Beispiel #27
0
def get_measurements(dir_path):
    frs = []
    for fp in glob(os.path.join(dir_path, '**', '*.csv'), recursive=True):
        frs.append(FrequencyResponse.read_from_csv(fp))
    return frs
Beispiel #28
0
def main():
    os.makedirs('smoothing', exist_ok=True)
    for file_path in glob('results/innerfidelity/sbaf-serious/*/*.csv'):
        fr = FrequencyResponse.read_from_csv(file_path)
        fr.smoothen_fractional_octave()

        light = fr.copy()
        light.name = 'Light'
        light.smoothen_fractional_octave(
            window_size=1 / 6,
            iterations=1,
            treble_f_lower=100,
            treble_f_upper=10000,
            treble_window_size=1 / 3,
            treble_iterations=1
        )

        heavy = fr.copy()
        heavy.name = 'Heavy'
        heavy.smoothen_fractional_octave(
            window_size=1 / 3,
            iterations=1,
            treble_f_lower=1000,
            treble_f_upper=6000,
            treble_window_size=1.3,
            treble_iterations=1
        )

        combination = fr.copy()
        combination.name = 'Combination'
        combination.error = np.max(np.vstack([light.error_smoothed, heavy.error_smoothed]), axis=0)
        combination.smoothen_fractional_octave(
            window_size=1 / 3,
            iterations=1,
            treble_f_lower=100,
            treble_f_upper=10000,
            treble_window_size=1 / 3,
            treble_iterations=1
        )

        window = fr.copy()
        window.name = 'Window'
        window.smoothen_fractional_octave(
            window_size=1.0,
            iterations=1,
            treble_window_size=1.0,
            treble_iterations=1
        )

        iterations = fr.copy()
        iterations.name = 'Iterations'
        iterations.smoothen_fractional_octave(
            window_size=1/3,
            iterations=100,
            treble_window_size=1/3,
            treble_iterations=60
        )

        fig, ax = fr.plot_graph(
            show=False,
            close=False,
            raw=False,
            smoothed=False,
            error=False,
            error_smoothed=False,
            equalization=False,
            parametric_eq=False,
            target=False,
            equalized=False
        )
        fig.set_size_inches(15, 10)
        legend = []
        ax.plot(fr.frequency, fr.error)
        legend.append('Raw error')
        # ax.plot(fr.frequency, fr.error_smoothed)
        # legend.append('Default smoothed error')
        # ax.plot(light.frequency, light.error_smoothed)
        # legend.append('Ligthly smoothed error)
        ax.plot(heavy.frequency, heavy.error_smoothed)
        legend.append('Heavily smoothed error')
        ax.plot(combination.frequency, combination.error_smoothed)
        legend.append('Combination smoothed error')
        # ax.plot(combination.frequency, -combination.error_smoothed)
        # legend.append('Equalization')
        ax.plot(light.frequency, fr.error - combination.error_smoothed)
        legend.append('Equalized')
        # ax.plot(window.frequency, window.error_smoothed)
        # legend.append(window.name)
        # ax.plot(iterations.frequency, iterations.error_smoothed)
        # legend.append(iterations.name)
        ax.set_ylim([-20, 20])

        ax.legend(legend)
        #plt.show(fig)
        fig.savefig(os.path.join('smoothing', fr.name + '.png'), dpi=150)
        plt.close(fig)
Beispiel #29
0
def main():
    # Filenames
    if_files = list(
        glob(os.path.join('innerfidelity', 'data', '**', '*.csv'),
             recursive=True))
    if_file_names = [os.path.split(os.path.abspath(f))[-1] for f in if_files]
    normalized_if_files = [normalize(s) for s in if_file_names]
    hp_files = list(
        glob(os.path.join('rtings', 'data', '**', '*.csv'), recursive=True))

    # Find matching files
    matching_if_files = []
    matching_hp_files = []
    for hp_file in hp_files:
        file_name = os.path.split(os.path.abspath(hp_file))[-1]
        for i in range(len(normalized_if_files)):
            if normalized_if_files[i] == normalize(file_name):
                matching_hp_files.append(hp_file)
                matching_if_files.append(if_files[i])

    # Write mathces to file for manual inspection
    df = pd.DataFrame(
        np.array([matching_hp_files, matching_if_files]).transpose())
    df.to_csv('matches.csv', index=False, header=False)

    fig, ax = plt.subplots()
    diffs = []
    # Calculate differences for all models
    if_compensation = FrequencyResponse.read_from_csv(
        os.path.join('innerfidelity', 'resources',
                     'innerfidelity_compensation_2017.csv'))
    if_compensation.interpolate()
    hp_compensation = FrequencyResponse.read_from_csv(
        os.path.join('rtings', 'resources', 'rtings_compensation.csv'))
    hp_compensation.interpolate()
    for i in range(len(matching_if_files)):
        if_fr = FrequencyResponse.read_from_csv(matching_if_files[i])
        if_fr.interpolate()
        if_fr.center()
        #if_fr.compensate(if_compensation)
        hp_fr = FrequencyResponse.read_from_csv(matching_hp_files[i])
        hp_fr.interpolate()
        hp_fr.center()
        #hp_fr.compensate(hp_compensation)
        #diff = FrequencyResponse(name=if_fr.name, frequency=if_fr.frequency, raw=hp_fr.error - if_fr.error)
        diff = FrequencyResponse(name=if_fr.name,
                                 frequency=if_fr.frequency,
                                 raw=hp_fr.raw - if_fr.raw)
        plt.plot(diff.frequency, diff.raw)
        diffs.append(diff.raw)

    # Average and smoothen difference
    f = FrequencyResponse.generate_frequencies()
    diffs = np.vstack(diffs)
    diff = np.mean(diffs, axis=0)
    std = np.std(diffs, axis=0)
    diff = FrequencyResponse(name='Rtings Raw to Innerfidelity Raw',
                             frequency=f,
                             raw=diff)
    #diff.smoothen(window_size=1/7, iterations=10)
    diff.smoothen_fractional_octave(window_size=1 / 5, iterations=100)
    diff.raw = diff.smoothed
    diff.smoothed = np.array([])

    plt.xlabel('Frequency (Hz)')
    plt.semilogx()
    plt.xlim([20, 20000])
    plt.ylabel('Amplitude (dBr)')
    plt.ylim([-15, 15])
    plt.grid(which='major')
    plt.grid(which='minor')
    plt.title('Rtings Raw to Innerfidelity Raw')
    ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:.0f}'))
    plt.show()

    fig, ax = diff.plot_graph(f_min=20, f_max=20000, show=False, color=None)
    ax.fill_between(diff.frequency,
                    diff.raw + std,
                    diff.raw - std,
                    facecolor='lightblue')
    plt.legend(['Rtings Raw to Innerfidelity Raw', 'Standard Deviation'])
    plt.ylim([-10, 10])
    fig.savefig(os.path.join('calibration', 'rtings_to_innerfidelity.png'),
                dpi=240)
    plt.show()
    diff.write_to_csv(
        os.path.join('calibration', 'rtings_to_innerfidelity.csv'))

    diff.raw *= -1
    diff.name = 'Innerfidelity Raw to Rtings Raw'
    fig, ax = diff.plot_graph(f_min=20, f_max=20000, show=False, color=None)
    ax.fill_between(diff.frequency,
                    diff.raw + std,
                    diff.raw - std,
                    facecolor='lightblue')
    plt.legend(['Innerfidelity Raw to Rtings Raw', 'Standard Deviation'])
    plt.ylim([-10, 10])
    fig.savefig(os.path.join('calibration', 'innerfidelity_to_rtings.png'),
                dpi=240)
    plt.show()
    diff.write_to_csv(
        os.path.join('calibration', 'innerfidelity_to_rtings.csv'))
Beispiel #30
0
# -*- coding: utf-8 -*-

from flask import Flask, request, jsonify, Response
import gevent.pywsgi
from frequency_response import FrequencyResponse

app = Flask(__name__)
compensations = {
    'innerfidelity_2016':
    FrequencyResponse.read_from_csv(
        'innerfidelity/resources/innerfidelity_compensation_2016.csv'),
    'innerfidelity_2017':
    FrequencyResponse.read_from_csv(
        'innerfidelity/resources/innerfidelity_compensation_2017.csv'),
    'innerfidelity_sbaf-serious':
    FrequencyResponse.read_from_csv(
        'innerfidelity/resources/innerfidelity_compensation_sbaf-serious.csv'),
    'headphonecom':
    FrequencyResponse.read_from_csv(
        'headphonecom/resources/headphonecom_compensation.csv'),
    'headphonecom_sbaf-serious':
    FrequencyResponse.read_from_csv(
        'headphonecom/resources/headphonecom_compensation_sbaf-serious.csv'),
    'harman_in-ear_2016':
    FrequencyResponse.read_from_csv('compensation/harman_in-ear_2016.csv'),
    'harman_in-ear_2017-1':
    FrequencyResponse.read_from_csv('compensation/harman_in-ear_2017-1.csv'),
    'harman_in-ear_2017-2':
    FrequencyResponse.read_from_csv('compensation/harman_in-ear_2017-2.csv'),
    'harman_over-ear_2013':
    FrequencyResponse.read_from_csv('compensation/harman_over-ear_2013.csv'),