예제 #1
0
    def _stable_pitches_to_notes(self, stable_pitches_hz,
                                 theoretical_intervals, tonic_hz):
        stable_pitches_cent = Converter.hz_to_cent(stable_pitches_hz, tonic_hz)
        # Finding nearest theoretical values of each stable pitch, identify the
        # name of this value and write to output
        stable_notes = {}  # Defining output (return) object
        for stable_pitch_cent, stable_pitch_hz in zip(stable_pitches_cent,
                                                      stable_pitches_hz):
            note_cent = TonicLastNote.find_nearest(
                theoretical_intervals.values(), stable_pitch_cent)

            if abs(stable_pitch_cent - note_cent) < self.pitch_threshold:
                for key, val in theoretical_intervals.iteritems():
                    if val == note_cent:
                        theoretical_pitch = Converter.cent_to_hz(
                            note_cent, tonic_hz)
                        stable_notes[key] = {
                            "performed_interval": {"value": stable_pitch_cent,
                                                   "unit": "cent"},
                            "theoretical_interval": {"value": note_cent,
                                                     "unit": "cent"},
                            "theoretical_pitch": {"value": theoretical_pitch,
                                                  "unit": "cent"},
                            "stable_pitch": {"value": stable_pitch_hz,
                                             "unit": "Hz"}}
                        break
        return stable_notes
    def check_tonic_with_octave_correction(self, tonic, distribution):
        # shift the distribution to tonic
        distribution.bins -= Converter.hz_to_cent(tonic, distribution.ref_freq)
        distribution.ref_freq = tonic

        # get the stable pitches
        peaks = distribution.detect_peaks()
        peak_idx = peaks[0]
        stable_pitches = distribution.bins[peak_idx]

        # find all the frequencies in the tonic candidate's pitch class
        pitches_in_tonic_pitch_class = [
            sp for sp in stable_pitches
            if min([sp % 1200, 1200 - (sp % 1200)]) < self.stable_pitch_dev]

        # sum all the pitch occurrences in the pitch distribution starting from
        # these pitches till their octave
        pitch_weights = []
        for pp in pitches_in_tonic_pitch_class:
            vals_in_octave = distribution.vals[(pp <= distribution.bins) *
                                               (distribution.bins < pp + 1200)]
            pitch_weights.append(np.sum(vals_in_octave))

        # the candidate which accumulates the highest weight is the tonic
        try:
            tonic_corr_cent = pitches_in_tonic_pitch_class[
                pitch_weights.index(max(pitch_weights))]

            return Converter.cent_to_hz(tonic_corr_cent, tonic)
        except ValueError:
            return None  # no stable pitch class found for the given frequency
 def _slice_pitch(self, pp, ti, tt):
     p_sliced = [p for t, p in zip(tt, pp) if ti[1] > t >= ti[0]]
     p_cent = Converter.hz_to_cent(p_sliced, self._dummy_ref_freq,
                                   min_freq=20.0)
     # pop nan and inf
     p_cent = p_cent[~np.isnan(p_cent)]
     p_cent = p_cent[~np.isinf(p_cent)]  # shouldn't exist, but anyways...
     return p_cent, p_sliced
    def _get_tunings(newtonic, note_models):
        for nm in note_models.values():
            interval = Converter.hz_to_cent(nm['stable_pitch']['Value'],
                                            newtonic['alignment']['Value'])
            nm['performed_interval'] = {'Value': interval, 'Unit': 'cent'}

            theo_pitch = Converter.cent_to_hz(
                nm['theoretical_interval']['Value'],
                newtonic['alignment']['Value'])
            nm['theoretical_pitch'] = {'Value': theo_pitch, 'Unit': 'Hz'}
예제 #5
0
    def _parse_pitch_input(pitch_in, tonic_freq):
        """
        Parses the pitch input from list, numpy array or file.

        If the input (or the file content) is a matrix, the method assumes the
        columns represent timestamps, pitch and "other columns".
        respectively. It only returns the second column in this case.

        :param pitch_in: pitch input, which is a list, numpy array or filename
        :param tonic_freq: the tonic frequency in Hz
        :return: parsed pitch track (numpy array)
        """
        # parse the pitch track from txt file, list or numpy array
        try:
            p = np.loadtxt(pitch_in)
        except ValueError:
            logger.debug('pitch_in is not a filename')
            p = np.array(pitch_in)

        p = p[:, 1] if p.ndim > 1 else p  # get the pitch stream

        # normalize wrt tonic
        return Converter.hz_to_cent(p, tonic_freq)
예제 #6
0
    def _parse_pitch_input(pitch_in, tonic_freq):
        """
        Parses the pitch input from list, numpy array or file.

        If the input (or the file content) is a matrix, the method assumes the
        columns represent timestamps, pitch and "other columns".
        respectively. It only returns the second column in this case.

        :param pitch_in: pitch input, which is a list, numpy array or filename
        :param tonic_freq: the tonic frequency in Hz
        :return: parsed pitch track (numpy array)
        """
        # parse the pitch track from txt file, list or numpy array
        try:
            p = np.loadtxt(pitch_in)
        except ValueError:
            logger.debug('pitch_in is not a filename')
            p = np.array(pitch_in)

        p = p[:, 1] if p.ndim > 1 else p  # get the pitch stream

        # normalize wrt tonic
        return Converter.hz_to_cent(p, tonic_freq)