<commit_before>""" Utility functions. """

import numpy as np
import peakutils
import functools
import time


def amp_to_dB(amp):
    """Converts amplitude to decibel units."""
    amp_db = 10.0 * np.log10(np.absolute(amp) ** 2)
    return amp_db


def freq_to_hertz(samplerate):
    """Returns function that converts frequency per-sample to per-second."""
    def to_hz(freq):
        return np.absolute(freq * samplerate)
    return to_hz


def pitch_to_hertz(midi_pitch):
    """Converts MIDI note number to its specified audio frequency (Hz).

    Based on 440 Hz concert pitch corresponding to MIDI pitch number of 69,
    and the doubling of frequency with each octave (12 semitones or MIDI note
    numbers).

    Args:
        midi_pitch (int): MIDI note number.

    Returns:
        hz (float): Audio frequency specified by the MIDI note number.
    """
    hz = 440 * (2 ** ((midi_pitch - 69) / 12))
    return hz

def time_to_sample(time, samplerate):
    """Return sample index closest to given time.

    Args:
        time (float): Time relative to the start of sample indexing.
        samplerate (int): Rate of sampling for the recording.

    Returns:
        sample (int): Index of the sample taken nearest to ``time``.
    """
    sample = int(time * samplerate)
    return sample


def sample_to_time(sample, samplerate):
    """Returns times corresponding to samples in a series."""
    time_ = sample / float(samplerate)
    return time_


def wait_while(toggle_attr):
    """Returns a decorator that waits for an instance attribute to be false."""
    def wait_while_decorator(instance_method):
        """Waits on a toggle attribute before executing an instance method."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            while getattr(self, toggle_attr):
                pass
            return instance_method(self, *args, **kwargs)

        return wrapper
    return wait_while_decorator


def set_true(toggle_attr):
    """Returns a decorator that enables an attribute during execution."""
    def set_true_decorator(instance_method):
        """Enables a boolean attribute while the decorated method executes."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            setattr(self, toggle_attr, True)
            output = instance_method(self, *args, **kwargs)
            setattr(self, toggle_attr, False)
            return output

        return wrapper
    return set_true_decorator


def if_true(toggle_attr):
    """Returns a decorator that executes its method if a condition is met."""
    def if_true_decorator(instance_method):
        """Execute the decorated method conditional on a toggle attribute."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            if getattr(self, toggle_attr):
                return instance_method(self, *args, **kwargs)

        return wrapper
    return if_true_decorator


def record_with_timepoints(timepoints_list_attr):
    """Returns a decorator that records entry and return times."""
    def record_with_timepoints_decorator(instance_method):
        """Append return value and entry and return times to attribute."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            start = time.time()
            output = instance_method(self, *args, **kwargs)
            stop = time.time()
            getattr(self, timepoints_list_attr).append((output, (start, stop)))
            return output

        return wrapper
    return record_with_timepoints_decorator


def get_peaks(y, x, thres):
    """Return the peaks in data that exceed a relative threshold."""
    try:
        peaks_idx = [peakutils.indexes(ch, thres=thres) for ch in y]
        peaks = [(x[idx], y[i][idx]) for i, idx in enumerate(peaks_idx)]
    except TypeError:  # amp not iterable
        return get_peaks([y], x, thres=thres)

    return peaks


def nearest_pow(num, base, rule=round):
    """Given a base, return power nearest to num.

    Parameters:
        num (float):
        base (float):
        rule (function):<commit_msg>Using ``time.perf_counter()`` for most precise timing available. Including start time (``time.time()``) as well because results of ``time.perf_counter`` are only useful as differences.<commit_after>""" Utility functions. """

import numpy as np
import peakutils
import functools
import time


def amp_to_dB(amp):
    """Converts amplitude to decibel units."""
    amp_db = 10.0 * np.log10(np.absolute(amp) ** 2)
    return amp_db


def freq_to_hertz(samplerate):
    """Returns function that converts frequency per-sample to per-second."""
    def to_hz(freq):
        return np.absolute(freq * samplerate)
    return to_hz


def pitch_to_hertz(midi_pitch):
    """Converts MIDI note number to its specified audio frequency (Hz).

    Based on 440 Hz concert pitch corresponding to MIDI pitch number of 69,
    and the doubling of frequency with each octave (12 semitones or MIDI note
    numbers).

    Args:
        midi_pitch (int): MIDI note number.

    Returns:
        hz (float): Audio frequency specified by the MIDI note number.
    """
    hz = 440 * (2 ** ((midi_pitch - 69) / 12))
    return hz

def time_to_sample(time, samplerate):
    """Return sample index closest to given time.

    Args:
        time (float): Time relative to the start of sample indexing.
        samplerate (int): Rate of sampling for the recording.

    Returns:
        sample (int): Index of the sample taken nearest to ``time``.
    """
    sample = int(time * samplerate)
    return sample


def sample_to_time(sample, samplerate):
    """Returns times corresponding to samples in a series."""
    time_ = sample / float(samplerate)
    return time_


def wait_while(toggle_attr):
    """Returns a decorator that waits for an instance attribute to be false."""
    def wait_while_decorator(instance_method):
        """Waits on a toggle attribute before executing an instance method."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            while getattr(self, toggle_attr):
                pass
            return instance_method(self, *args, **kwargs)

        return wrapper
    return wait_while_decorator


def set_true(toggle_attr):
    """Returns a decorator that enables an attribute during execution."""
    def set_true_decorator(instance_method):
        """Enables a boolean attribute while the decorated method executes."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            setattr(self, toggle_attr, True)
            output = instance_method(self, *args, **kwargs)
            setattr(self, toggle_attr, False)
            return output

        return wrapper
    return set_true_decorator


def if_true(toggle_attr):
    """Returns a decorator that executes its method if a condition is met."""
    def if_true_decorator(instance_method):
        """Execute the decorated method conditional on a toggle attribute."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            if getattr(self, toggle_attr):
                return instance_method(self, *args, **kwargs)

        return wrapper
    return if_true_decorator


def record_with_timepoints(record_attr):
    """Returns a decorator that records entry and return times."""
    def record_with_timepoints_decorator(instance_method):
        """Append return value and entry and return times to attribute."""
        @functools.wraps(instance_method)
        def wrapper(self, *args, **kwargs):
            start_time = time.time()
            start_clock = time.perf_counter()
            output = instance_method(self, *args, **kwargs)
            stop_clock = time.perf_counter()
            getattr(self, record_attr).append((output, start_time,
                                               (start_clock, stop_clock)))
            return output
        return wrapper
    return record_with_timepoints_decorator


def get_peaks(y, x, thres):
    """Return the peaks in data that exceed a relative threshold."""
    try:
        peaks_idx = [peakutils.indexes(ch, thres=thres) for ch in y]
        peaks = [(x[idx], y[i][idx]) for i, idx in enumerate(peaks_idx)]
    except TypeError:  # amp not iterable
        return get_peaks([y], x, thres=thres)

    return peaks


def nearest_pow(num, base, rule=round):
    """Given a base, return power nearest to num.

    Parameters:
        num (float):
        base (float):
        rule (function):
{'fraction_non_alphanumeric': 0.09523809523809523, 'fraction_numerical': 0.004878048780487805, 'mean_word_length': 2.882326420198377, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3896249', 'n_tokens_mistral': 2504, 'n_tokens_neox': 2380, 'n_words': 825}