Esempio n. 1
0
    def process(self, item, file_paths, target_dir=None):
        if item.form == 'ignore':
            return

        if target_dir is None:
            raise TypeError('"target_dir" must be given')

        avg_fr = FrequencyResponse(name=item.true_name)
        avg_fr.raw = np.zeros(avg_fr.frequency.shape)
        for fp in file_paths:
            with open(fp, 'r', encoding='utf-8') as fh:
                s = fh.read()

            freq = []
            raw = []
            for line in s.split('\n'):
                if len(line) == 0 or line[0] == '*':
                    # Skip empty lines and comments
                    if 'C-weighting compensation: On' in line:
                        print(f'C-weighted measurement: {item.false_name}')
                    continue

                frp = line.split(', ')
                if len(frp) == 1:
                    frp = line.split('\t')
                if len(frp) == 1:
                    frp = line.split(' ')
                if len(frp) == 2:
                    f, r = frp
                elif len(frp) == 3:
                    f, r, p = frp
                else:
                    # Must be comment line
                    continue

                if f == '?' or r == '?':
                    # Skip lines with missing data
                    continue

                try:
                    freq.append(float(f))
                    raw.append(float(r))
                except ValueError as err:
                    # Failed to convert values to floats, must be header or comment row, skip
                    continue

            # Create standard fr object
            fr = FrequencyResponse(name=item.true_name, frequency=freq, raw=raw)
            fr.interpolate()
            fr.center()
            avg_fr.raw += fr.raw

        avg_fr.raw /= len(file_paths)

        # Save
        dir_path = os.path.join(target_dir, avg_fr.name)
        os.makedirs(dir_path, exist_ok=True)
        file_path = os.path.join(dir_path, f'{avg_fr.name}.csv')
        avg_fr.write_to_csv(file_path)
        print(f'Saved "{avg_fr.name}" to "{file_path}"')
Esempio n. 2
0
    def process(self, item, file_paths):
        fr = FrequencyResponse(name=item.true_name)
        fr.raw = np.zeros(fr.frequency.shape)
        for fp in file_paths:
            if re.search(r'\.mdat$', fp):
                # Read mdat file for Gras headphone measurements
                raise TypeError(
                    'Crinacle\'s Gras measurements are not supported yet!')
            else:
                # Read text file for IEM and Ears-711 headphone measurements
                with open(fp, 'r', encoding='utf-8') as fh:
                    s = fh.read()

            freq = []
            raw = []
            for line in s.split('\n'):
                if len(line) == 0 or line[0] == '*':
                    # Skip empty lines and comments
                    if 'C-weighting compensation: On' in line:
                        print(f'C-weighted measurement: {item.false_name}')
                    continue

                frp = line.split(' ')
                if len(frp) == 1:
                    frp = line.split('\t')
                if len(frp) == 2:
                    f, r = frp
                elif len(frp) == 3:
                    f, r, p = frp
                else:
                    # Must be comment line
                    continue

                if f == '?' or r == '?':
                    # Skip lines with missing data
                    continue

                try:
                    freq.append(float(f))
                    raw.append(float(r))
                except ValueError as err:
                    # Failed to convert values to floats, must be header or comment row, skip
                    continue

            # Create standard fr object
            _fr = FrequencyResponse(name=item.true_name,
                                    frequency=freq,
                                    raw=raw)
            _fr.interpolate()
            _fr.center()
            fr.raw += _fr.raw

        fr.raw /= len(file_paths)

        # Save
        dir_path = os.path.join(DIR_PATH, 'data', item.form, fr.name)
        os.makedirs(dir_path, exist_ok=True)
        file_path = os.path.join(dir_path, f'{fr.name}.csv')
        fr.write_to_csv(file_path)
        print(f'Saved "{fr.name}" to "{file_path}"')
    def parse_image(im, model):
        """Parses graph image downloaded from innerfidelity.com"""
        # Crop by left and right edges
        box = (69, 31, 550, 290)
        im = im.crop(box)

        px_a_max = 0
        px_a_min = im.size[1]
        # im.show()

        # X axis
        f_min = 20
        f_max = 20000
        f_step = (f_max / f_min)**(1 / im.size[0])
        f = [f_min]
        for _ in range(1, im.size[0]):
            f.append(f[-1] * f_step)

        # Y axis
        a_max = 150
        a_min = 66
        a_res = (a_max - a_min) / (px_a_min - px_a_max)

        # Try blue curve
        _im = im.copy()
        inspection = _im.load()
        amplitude, _im, _inspection = ReferenceAudioAnalyzerCrawler.find_curve(
            _im, inspection, 203, 206, 0.8, 1.0, a_max, a_res)
        if len([x for x in amplitude if x is None]) >= 0.5 * len(amplitude):
            # More than half of the pixels were discarded, try green curve
            _im = im.copy()
            inspection = _im.load()
            amplitude, _im, _inspection = ReferenceAudioAnalyzerCrawler.find_curve(
                _im, inspection, 119, 121, 0.8, 1.0, a_max, a_res)

        # Inspection image
        draw = ImageDraw.Draw(_im)
        x0 = np.log(30 / f_min) / np.log(f_step)
        x1 = np.log(10000 / f_min) / np.log(f_step)
        y_0 = px_a_max + 12 / a_res
        y_1 = px_a_min - 12 / a_res
        draw.rectangle(((x0, y_0), (x1, y_1)), outline='magenta')
        draw.rectangle(((x0 + 1, y_0 + 1), (x1 - 1, y_1 - 1)),
                       outline='magenta')

        # Create frequency response
        fr = FrequencyResponse(model, f, amplitude)
        fr.interpolate()
        if len(fr.frequency) < 2:
            im.show()
            raise ValueError(f'Failed to parse image for {fr.name}')
        fr.smoothen_fractional_octave(window_size=1 / 3,
                                      treble_window_size=1 / 3)
        fr.raw = fr.smoothed.copy()
        fr.smoothed = np.array([])
        fr.center()

        return fr, _im
Esempio n. 4
0
def save(df, column, name):
    fr = FrequencyResponse(name=name,
                           frequency=df['Frequency'],
                           raw=df[column])
    fr.interpolate()
    fr.center()
    name = name.lower().replace(' ', '_')
    fr.write_to_csv('compensation/{}.csv'.format(name))
    fr.plot_graph(file_path='compensation/{}.png'.format(name),
                  show=False,
                  color=None)

    ind = np.argmin(fr.raw[:400])
    fr.raw[:ind] = fr.raw[ind]
    fr.write_to_csv('compensation/{}_wo_bass.csv'.format(name))
    fr.plot_graph(file_path='compensation/{}_wo_bass.png'.format(name),
                  show=False,
                  color=None)
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)
Esempio n. 6
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()
Esempio n. 7
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()
Esempio n. 8
0
def equal_loudness_contour(phon):
    f = [
        20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500,
        630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000,
        10000, 12500
    ]
    af = [
        0.532, 0.506, 0.480, 0.455, 0.432, 0.409, 0.387, 0.367, 0.349, 0.330,
        0.315, 0.301, 0.288, 0.276, 0.267, 0.259, 0.253, 0.250, 0.246, 0.244,
        0.243, 0.243, 0.243, 0.242, 0.242, 0.245, 0.254, 0.271, 0.301
    ]
    Lu = [
        -31.6, -27.2, -23.0, -19.1, -15.9, -13.0, -10.3, -8.1, -6.2, -4.5,
        -3.1, -2.0, -1.1, -0.4, 0.0, 0.3, 0.5, 0.0, -2.7, -4.1, -1.0, 1.7, 2.5,
        1.2, -2.1, -7.1, -11.2, -10.7, -3.1
    ]
    Tf = [
        78.5, 68.7, 59.5, 51.1, 44.0, 37.5, 31.5, 26.5, 22.1, 17.9, 14.4, 11.4,
        8.6, 6.2, 4.4, 3.0, 2.2, 2.4, 3.5, 1.7, -1.3, -4.2, -6.0, -5.4, -1.5,
        6.0, 12.6, 13.9, 12.3
    ]

    Ln = phon
    Lps = []
    for i in range(0, len(f)):
        Af = 0.00447 * (10.0**(Ln / 40.0) - 1.15) + (10.0**((
            (Tf[i] + Lu[i]) / 10.0) - 9.0) / 2.5)**af[i]
        Lp = ((10.0 / af[i]) * math.log10(Af)) - Lu[i] + 94.0
        Lps.append(Lp)
    Lps = np.array(Lps)

    fr = FrequencyResponse(name='{} phon Equal Loudness Contour'.format(phon),
                           frequency=f,
                           raw=Lps)
    fr.interpolate(pol_order=3, f_min=20, f_max=12500)
    fr.center()
    return fr
Esempio n. 9
0
    def parse_image(im,
                    model,
                    px_top=800,
                    px_bottom=4400,
                    px_left=0,
                    px_right=2500):
        """Parses graph image downloaded from innerfidelity.com"""
        # Crop out everything but graph area (roughly)
        box = (px_left, px_top, im.size[0] - px_right, im.size[1] - px_bottom)
        im = im.crop(box)
        # im.show()

        # Find graph edges
        v_lines = ImageGraphParser.find_lines(im, 'vertical')
        h_lines = ImageGraphParser.find_lines(im, 'horizontal')

        # Crop by graph edges
        box = (v_lines[0], h_lines[0], v_lines[1], h_lines[1])
        im = im.crop(box)
        # im.show()

        # X axis
        f_min = 10
        f_max = 20000
        f_step = (f_max / f_min)**(1 / im.size[0])
        f = [f_min]
        for _ in range(1, im.size[0]):
            f.append(f[-1] * f_step)

        # Y axis
        a_max = 30
        a_min = -20
        a_res = (a_max - a_min) / im.size[1]

        _im = im.copy()
        pix = _im.load()
        amplitude = []
        y_legend = 40 / 50 * im.size[1]
        x0_legend = np.log(70 / f_min) / np.log(f_step)
        x1_legend = np.log(1000 / f_min) / np.log(f_step)
        # Iterate each column
        for x in range(im.size[0]):
            pxs = []  # Graph pixels
            # Iterate each row (pixel in column)
            for y in range(im.size[1]):
                if y > y_legend and x0_legend < x < x1_legend:
                    # Skip pixels in the legend box
                    continue

                # Convert read RGB pixel values and convert to HSV
                h, s, v = colorsys.rgb_to_hsv(
                    *[v / 255.0 for v in im.getpixel((x, y))])
                # Graph pixels are colored
                if 0.7 < s < 0.9 and 20 / 360 < h < 30 / 360:
                    pxs.append(float(y))
                else:
                    p = im.getpixel((x, y))
                    pix[x, y] = (int(0.3 * p[0]), int(255 * 0.7 + 0.3 * p[1]),
                                 int(0.3 * p[2]))
            if not pxs:
                # No graph pixels found on this column
                amplitude.append(None)
            else:
                # Mean of recorded pixels
                v = np.mean(pxs)
                # Convert to dB value
                v = a_max - v * a_res
                amplitude.append(v)

        # Inspection image
        draw = ImageDraw.Draw(_im)
        x0 = np.log(20 / f_min) / np.log(f_step)
        x1 = np.log(10000 / f_min) / np.log(f_step)
        draw.rectangle(((x0, 10 / a_res), (x1, 40 / a_res)), outline='magenta')
        draw.rectangle(((x0 + 1, 10 / a_res + 1), (x1 - 1, 40 / a_res - 1)),
                       outline='magenta')

        fr = FrequencyResponse(model, f, amplitude)
        fr.interpolate()
        fr.center()
        return fr, _im
Esempio n. 10
0
def parse_image(im, model):
    """Parses graph image downloaded from innerfidelity.com"""
    # Crop by left and right edges
    box = (69, 31, 550, 290)
    im = im.crop(box)

    px_a_max = 0
    px_a_min = im.size[1]
    #im.show()

    # X axis
    f_min = 20
    f_max = 20000
    f_step = (f_max / f_min)**(1 / im.size[0])
    f = [f_min]
    for _ in range(1, im.size[0]):
        f.append(f[-1] * f_step)

    # Y axis
    a_max = 150
    a_min = 66
    a_res = (a_max - a_min) / (px_a_min - px_a_max)

    # Colors
    #line_color = np.array([50, 155, 254])
    line_color = np.array([0, 135, 0])

    _im = im.copy()
    inspection = _im.load()
    amplitude = []
    # Iterate each column
    for x in range(im.size[0]):
        pxs = []  # Graph pixels
        # Iterate each row (pixel in column)
        for y in range(im.size[1]):
            # Convert read RGB pixel values and convert to HSV
            rgba = im.getpixel((x, y))
            # Graph pixels are colored
            if np.mean(np.abs(line_color - rgba[:3])) < 15:
                pxs.append(float(y))
            else:
                p = im.getpixel((x, y))
                inspection[x,
                           y] = (int(0.3 * p[0]), int(255 * 0.7 + 0.3 * p[1]),
                                 int(0 + 0.3 * p[2]))
        if not pxs:
            # No graph pixels found on this column
            amplitude.append(None)
        else:
            # Mean of recorded pixels
            v = np.mean(pxs)
            # Convert to dB value
            v = a_max - v * a_res
            amplitude.append(v)

    # Inspection image
    draw = ImageDraw.Draw(_im)
    x0 = np.log(30 / f_min) / np.log(f_step)
    x1 = np.log(10000 / f_min) / np.log(f_step)
    y_0 = px_a_max + 12 / a_res
    y_1 = px_a_min - 12 / a_res
    draw.rectangle(((x0, y_0), (x1, y_1)), outline='magenta')
    draw.rectangle(((x0 + 1, y_0 + 1), (x1 - 1, y_1 - 1)), outline='magenta')

    # Create frequency response
    fr = FrequencyResponse(model, f, amplitude)
    fr.interpolate()
    fr.center()

    return fr, _im
Esempio n. 11
0
def main():
    # Read name index
    name_index = dict()
    df = pd.read_csv(os.path.join(DIR_PATH, 'name_index.tsv'),
                     sep='\t',
                     header=None)
    # Replace empty cells with empty strings
    df = df.fillna('')
    df.columns = ['name', 'full_name', 'comment']
    records = df.to_dict('records')
    full_names = set()
    for record in records:
        if record['full_name'] in full_names:
            warnings.warn(
                'Duplicate entry in name index with full name: "{}".'.format(
                    record['full_name']))
            continue
        name_index[record['name']] = record

    data = dict()
    for file_path in glob(os.path.join(DIR_PATH, 'raw_data', '*.txt')):
        name = os.path.split(file_path)[1]
        # Remove ".txt" and " R" or " L" suffix
        name = re.sub('\.txt$', '', name)
        name = re.sub(' (L|R)', '', name)
        if name not in name_index:
            warnings.warn(
                '"{}" missing from name index, skipping.'.format(name))
            continue
        if name_index[name]['comment'] in [
                'ignore', 'onear'
        ] or not name_index[name]['full_name']:
            warnings.warn('Skipping "{}".'.format(name))
            continue
        name = name_index[name]['full_name']
        if name not in data:
            data[name] = []

        # Read file
        with open(file_path, 'r') as f:
            s = f.read()

        freq = []
        raw = []
        for line in s.split('\n'):
            if len(line) == 0 or line[0] == '*':
                # Skip empty lines and comments
                if 'C-weighting compensation: On' in line:
                    warnings.warn('C-weighted measurement: ' + name)
                continue

            frp = line.split(' ')
            if len(frp) == 1:
                frp = line.split('\t')
            if len(frp) == 2:
                f, r = frp
            elif len(frp) == 3:
                f, r, p = frp
            else:
                # Must be comment line
                continue

            if f == '?' or r == '?':
                # Skip lines with missing data
                continue

            try:
                freq.append(float(f))
                raw.append(float(r))
            except ValueError as err:
                # Failed to convert values to floats, must be header or comment row, skip
                continue

        # Create standard fr object
        fr = FrequencyResponse(name=name, frequency=freq, raw=raw)
        fr.interpolate()
        fr.center()
        data[name].append(fr)

    if not os.path.isdir(os.path.join(DIR_PATH, 'inspection')):
        os.makedirs(os.path.join(DIR_PATH, 'inspection'))

    # Iterate all models
    for name, frs in data.items():
        # Average SPL data from all measurements for this model (so Left and Right)
        raw = np.mean([fr.raw for fr in frs], axis=0)
        # Save as CSV
        fr = FrequencyResponse(name=name, frequency=frs[0].frequency, raw=raw)
        dir_path = os.path.join(DIR_PATH, 'data', 'inear', name)
        if not os.path.isdir(dir_path):
            os.makedirs(dir_path)
        fr.write_to_csv(os.path.join(dir_path, name + '.csv'))
        # Save inspection image
        fr.plot_graph(show=False,
                      file_path=os.path.join(DIR_PATH, 'inspection',
                                             name + '.png'))
        plt.close()
Esempio n. 12
0
def parse_image(im, model, channel):
    """Parses graph image downloaded from innerfidelity.com"""
    # Find graph edges
    v_lines = ImageGraphParser.find_lines(im,
                                          'vertical',
                                          line_color=(204, 204, 204))
    h_lines = ImageGraphParser.find_lines(im,
                                          'horizontal',
                                          line_color=(204, 204, 204))
    h_lines = np.array(h_lines)

    # Crop by left and right edges
    box = (v_lines[0], h_lines[0], v_lines[-1], im.size[1])
    im = im.crop(box)
    h_lines -= h_lines[
        0]  # Cropped to first line, subtract distance from all lines

    # Add missing horizontal lines 115 - 55
    deltas = []
    for i in range(1, len(h_lines)):
        deltas.append(h_lines[i] - h_lines[i - 1])
    delta = max(deltas, key=deltas.count)
    _h_lines = list(h_lines[:1])
    for _ in range(12):  # First line + 12 additional lines
        # Estimate where the line should be
        estimate = _h_lines[-1] + delta
        # Get original lines which are at most 1 pixel away from the estimate
        originals = h_lines[np.abs(np.array(h_lines) - estimate) <= 1]
        if len(originals):
            # Original line found, use it
            estimate = originals[0]
        # Add new line
        _h_lines.append(estimate)
    h_lines = _h_lines

    # Crop bottom
    box = (0, 0, im.size[0], h_lines[-1])
    im = im.crop(box)

    px_a_max = 0
    px_a_min = h_lines[-1]
    #im.show()

    # X axis
    f_min = 20
    f_max = 20000
    f_step = (f_max / f_min)**(1 / im.size[0])
    f = [f_min]
    for _ in range(1, im.size[0]):
        f.append(f[-1] * f_step)

    # Y axis
    a_max = 115
    a_min = 55
    a_res = (a_max - a_min) / (px_a_min - px_a_max)

    # Colors
    color_left = (79, 129, 189)
    color_right = (119, 119, 119)

    _im = im.copy()
    inspection = _im.load()
    amplitude = []
    # Iterate each column
    for x in range(im.size[0]):
        pxs = []  # Graph pixels
        # Iterate each row (pixel in column)
        for y in range(im.size[1]):
            # Convert read RGB pixel values and convert to HSV
            rgba = im.getpixel((x, y))
            r, g, b = rgba[:3]
            # Graph pixels are colored
            if (channel == 'left' and
                (r, g, b) == color_left) or (channel == 'right' and
                                             (r, g, b) == color_right):
                pxs.append(float(y))
            else:
                p = im.getpixel((x, y))
                inspection[x,
                           y] = (int(0.3 * p[0]), int(255 * 0.7 + 0.3 * p[1]),
                                 int(0 + 0.3 * p[2]))
        if not pxs:
            # No graph pixels found on this column
            amplitude.append(None)
        else:
            # Mean of recorded pixels
            v = np.mean(pxs)
            # Convert to dB value
            v = a_max - v * a_res
            amplitude.append(v)

    # Inspection image
    draw = ImageDraw.Draw(_im)
    x0 = np.log(30 / f_min) / np.log(f_step)
    x1 = np.log(10000 / f_min) / np.log(f_step)
    y_0 = px_a_max + 10 / a_res
    y_1 = px_a_min - 10 / a_res
    draw.rectangle(((x0, y_0), (x1, y_1)), outline='magenta')
    draw.rectangle(((x0 + 1, y_0 + 1), (x1 - 1, y_1 - 1)), outline='magenta')

    # Create frequency response
    fr = FrequencyResponse(model, f, amplitude)
    fr.interpolate()
    fr.center()

    return fr, _im
Esempio n. 13
0
    def process(self, item, url):
        json_file = Crawler.download(url, item.true_name,
                                     os.path.join(DIR_PATH, 'json'))
        if json_file is not None:
            with open(os.path.join(DIR_PATH, 'json', f'{item.true_name}.json'),
                      'r',
                      encoding='utf-8') as fh:
                json_data = json.load(fh)
            fr, target = RtingsCrawler.parse_json(json_data)
            fr.name = item.true_name
        else:
            # No frequency response available, download bass, mid and treble
            # Bass
            Crawler.download(
                url.replace('frequency-response-14.json', 'bass.json'),
                f'{item.true_name}-bass', os.path.join(DIR_PATH, 'json'))
            with open(os.path.join(DIR_PATH, 'json',
                                   f'{item.true_name}-bass.json'),
                      'r',
                      encoding='utf-8') as fh:
                bass_fr, bass_target = self.parse_json(json.load(fh))
            # Mid
            Crawler.download(
                url.replace('frequency-response-14.json', 'mid.json'),
                f'{item.true_name}-mid', os.path.join(DIR_PATH, 'json'))
            with open(os.path.join(DIR_PATH, 'json',
                                   f'{item.true_name}-mid.json'),
                      'r',
                      encoding='utf-8') as fh:
                mid_fr, mid_target = self.parse_json(json.load(fh))
            # Treble
            Crawler.download(
                url.replace('frequency-response-14.json', 'treble.json'),
                f'{item.true_name}-treble', os.path.join(DIR_PATH, 'json'))
            with open(os.path.join(DIR_PATH, 'json',
                                   f'{item.true_name}-treble.json'),
                      'r',
                      encoding='utf-8') as fh:
                treble_fr, treble_target = self.parse_json(json.load(fh))
            fr = FrequencyResponse(
                name=item.true_name,
                frequency=np.concatenate(
                    [bass_fr.frequency, mid_fr.frequency,
                     treble_fr.frequency]),
                raw=np.concatenate([bass_fr.raw, mid_fr.raw, treble_fr.raw]))
            target = FrequencyResponse(name=item.true_name,
                                       frequency=np.concatenate([
                                           bass_target.frequency,
                                           mid_target.frequency,
                                           treble_target.frequency
                                       ]),
                                       raw=np.concatenate([
                                           bass_target.raw, mid_target.raw,
                                           treble_target.raw
                                       ]))

        fr.interpolate()
        if np.std(fr.raw) == 0:
            # Frequency response data has non-zero target response, use that
            target.interpolate()
            target = target
            print(f'Using target for {fr.name}')
        elif item.form == '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()

        # Inspection
        dir_path = os.path.join(DIR_PATH, 'inspection')
        os.makedirs(dir_path, exist_ok=True)
        file_path = os.path.join(dir_path, f'{fr.name}.png')
        fig, ax = fr.plot_graph(file_path=file_path, show=False)
        plt.close(fig)

        # Write to file
        dir_path = os.path.join(DIR_PATH, 'data', item.form, fr.name)
        os.makedirs(dir_path, exist_ok=True)
        file_path = os.path.join(dir_path, fr.name + '.csv')
        fr.write_to_csv(file_path)
        print(f'Saved "{fr.name}" to "{file_path}"')
Esempio n. 14
0
def main():
    data = dict()
    for file_path in glob(os.path.join(DIR_PATH, 'raw_data', '*.txt')):
        # Read name of the IEM from file path
        _, file_name = os.path.split(file_path)
        name = '.'.join(file_name.split('.')[:-1])
        name = name[:-2]  # Remove channel from name
        if name not in data:
            data[name] = []

        # Read file
        with open(file_path, 'r') as f:
            s = f.read()

        freq = []
        raw = []
        for line in s.split('\n'):
            if len(line) == 0 or line[0] == '*':
                # Skip empty lines and comments
                if 'C-weighting compensation: On' in line:
                    warnings.warn('C-weighted measurement: ' + name)
                continue

            frp = line.split(' ')
            if len(frp) == 1:
                frp = line.split('\t')
            if len(frp) == 2:
                f, r = frp
            elif len(frp) == 3:
                f, r, p = frp
            else:
                # Must be comment line
                continue

            if f == '?' or r == '?':
                # Skip lines with missing data
                continue

            try:
                freq.append(float(f))
                raw.append(float(r))
            except ValueError as err:
                # Failed to convert values to floats, must be header or comment row, skip
                continue

        # Create standard fr object
        fr = FrequencyResponse(name=name, frequency=freq, raw=raw)
        fr.interpolate()
        fr.center()
        data[name].append(fr)

    if os.path.exists(os.path.join(DIR_PATH, 'inspection')):
        os.makedirs(os.path.join(DIR_PATH, 'inspection'))

    # Iterate all models
    for name, frs in data.items():
        # Average SPL data from all measurements for this model (so Left and Right)
        raw = np.mean([fr.raw for fr in frs], axis=0)
        # Save as CSV
        fr = FrequencyResponse(name=name, frequency=frs[0].frequency, raw=raw)
        fr.write_to_csv(os.path.join(DIR_PATH, 'data', name + '.csv'))
        # Save inspection image
        fr.plot_graph(show=False,
                      file_path=os.path.join(DIR_PATH, 'inspection',
                                             name + '.png'))