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())
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)
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')
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)
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()
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)
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})')
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'))
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)
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)
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()
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)
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)
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()
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()
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'))
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()
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'))
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))
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
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)
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'))
def measurements(dir_path): frs = [] for fp in glob(os.path.join(dir_path, '*', '*.csv')): frs.append(FrequencyResponse.read_from_csv(fp)) return frs
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))
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}' )
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
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)
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'))
# -*- 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'),