# mir_eval.multipitch

The goal of multiple f0 (multipitch) estimation and tracking is to identify all of the active fundamental frequencies in each time frame in a complex music signal.

## Conventions

Multipitch estimates are represented by a timebase and a corresponding list of arrays of frequency estimates. Frequency estimates may have any number of frequency values, including 0 (represented by an empty array). Time values are in units of seconds and frequency estimates are in units of Hz.

The timebase of the estimate time series should ideally match the timebase of the reference time series, but if this is not the case, the estimate time series is resampled using a nearest neighbor interpolation to match the estimate. Time values in the estimate time series that are outside of the range of the reference time series are given null (empty array) frequencies.

By default, a frequency is “correct” if it is within 0.5 semitones of a reference frequency. Frequency values are compared by first mapping them to log-2 semitone space, where the distance between semitones is constant. Chroma-wrapped frequency values are computed by taking the log-2 frequency values modulo 12 to map them down to a single octave. A chroma-wrapped frequency estimate is correct if it’s single-octave value is within 0.5 semitones of the single-octave reference frequency.

The metrics are based on those described in [1] and [2].

## Metrics

- `mir_eval.multipitch.metrics()`: Precision, Recall, Accuracy, Substitution, Miss, False Alarm, and Total Error scores based both on raw frequency values and values mapped to a single octave (chroma).

## References

[1]

G. E. Poliner, and D. P. W. Ellis, “A Discriminative Model for Polyphonic Piano Transription”, EURASIP Journal on Advances in Signal Processing, 2007(1):154-163, Jan. 2007.

[2]

Bay, M., Ehmann, A. F., & Downie, J. S. (2009). Evaluation of Multiple-F0 Estimation and Tracking Systems. In ISMIR (pp. 315-320).

mir_eval.multipitch.validate(ref_time, ref_freqs, est_time, est_freqs)

  Check that the time and frequency inputs are well-formed.

  Parameters:
    ref_time np.ndarray

      reference time stamps in seconds

    ref_freqs list of np.ndarray

      reference frequencies in Hz

    est_time np.ndarray

      estimate time stamps in seconds

    est_freqs list of np.ndarray

      estimated frequencies in Hz

mir_eval.multipitch.resample_multipitch(times, frequencies, target_times)

  Resamples multipitch time series to a new timescale using nearest neighbor interpolation. Values in `target_times` outside the range of `times` return no pitch estimate.

  Parameters:
    times np.ndarray

      Array of time stamps

    frequencies list of np.ndarray

      List of np.ndarrays of frequency values

    target_times np.ndarray

      Array of target time stamps

  Returns:
    frequencies_resampled list of numpy arrays

      Frequency list of lists resampled to new timebase

mir_eval.multipitch.frequencies_to_midi(frequencies, ref_frequency=440.0)

  Convert frequencies to continuous MIDI values.

  Parameters:
    frequencies list of np.ndarray

      Original frequency values

    ref_frequency float

      reference frequency in Hz.

  Returns:
    frequencies_midi list of np.ndarray

      Continuous MIDI frequency values.

mir_eval.multipitch.midi_to_chroma(frequencies_midi)

  Wrap MIDI frequencies to a single octave (chroma).

  Parameters:
    frequencies_midi list of np.ndarray

      Continuous MIDI note frequency values.

  Returns:
    frequencies_chroma list of np.ndarray

      Midi values wrapped to one octave.

mir_eval.multipitch.compute_num_freqs(frequencies)

  Compute the number of frequencies for each time point.

  Parameters:
    frequencies list of np.ndarray

      Frequency values

  Returns:
    num_freqs np.ndarray

      Number of frequencies at each time point.

mir_eval.multipitch.compute_num_true_positives(ref_freqs, est_freqs, window=0.5, chroma=False)

  Compute the number of true positives in an estimate given a reference. A frequency is correct if it is within a quartertone of the correct frequency.

  Parameters:
    ref_freqs list of np.ndarray

      reference frequencies (MIDI)

    est_freqs list of np.ndarray

      estimated frequencies (MIDI)

    window float

      Window size, in semitones

    chroma bool

      If True, computes distances modulo n. If True, `ref_freqs` and `est_freqs` should be wrapped modulo n.

  Returns:
    true_positives np.ndarray

      Array the same length as ref_freqs containing the number of true positives.

mir_eval.multipitch.compute_accuracy(true_positives, n_ref, n_est)

  Compute accuracy metrics.

  Parameters:
    true_positives np.ndarray

      Array containing the number of true positives at each time point.

    n_ref np.ndarray

      Array containing the number of reference frequencies at each time point.

    n_est np.ndarray

      Array containing the number of estimate frequencies at each time point.

  Returns:
    precision float

      `sum(true_positives)/sum(n_est)`

    recall float

      `sum(true_positives)/sum(n_ref)`

    acc float

      `sum(true_positives)/sum(n_est + n_ref - true_positives)`

mir_eval.multipitch.compute_err_score(true_positives, n_ref, n_est)

  Compute error score metrics.

  Parameters:
    true_positives np.ndarray

      Array containing the number of true positives at each time point.

    n_ref np.ndarray

      Array containing the number of reference frequencies at each time point.

    n_est np.ndarray

      Array containing the number of estimate frequencies at each time point.

  Returns:
    e_sub float

      Substitution error

    e_miss float

      Miss error

    e_fa float

      False alarm error

    e_tot float

      Total error

mir_eval.multipitch.metrics(ref_time, ref_freqs, est_time, est_freqs, **kwargs)

  Compute multipitch metrics. All metrics are computed at the ‘macro’ level such that the frame true positive/false positive/false negative rates are summed across time and the metrics are computed on the combined values.

  Parameters:
    ref_time np.ndarray

      Time of each reference frequency value

    ref_freqs list of np.ndarray

      List of np.ndarrays of reference frequency values

    est_time np.ndarray

      Time of each estimated frequency value

    est_freqs list of np.ndarray

      List of np.ndarrays of estimate frequency values

    **kwargs

      Additional keyword arguments which will be passed to the appropriate metric or preprocessing functions.

  Returns:
    precision float

      Precision (TP/(TP + FP))

    recall float

      Recall (TP/(TP + FN))

    accuracy float

      Accuracy (TP/(TP + FP + FN))

    e_sub float

      Substitution error

    e_miss float

      Miss error

    e_fa float

      False alarm error

    e_tot float

      Total error

    precision_chroma float

      Chroma precision

    recall_chroma float

      Chroma recall

    accuracy_chroma float

      Chroma accuracy

    e_sub_chroma float

      Chroma substitution error

    e_miss_chroma float

      Chroma miss error

    e_fa_chroma float

      Chroma false alarm error

    e_tot_chroma float

      Chroma total error

  Examples

      >>> ref_time, ref_freqs = mir_eval.io.load_ragged_time_series(
      ...     'reference.txt')
      >>> est_time, est_freqs = mir_eval.io.load_ragged_time_series(
      ...     'estimated.txt')
      >>> metris_tuple = mir_eval.multipitch.metrics(
      ...     ref_time, ref_freqs, est_time, est_freqs)

mir_eval.multipitch.evaluate(ref_time, ref_freqs, est_time, est_freqs, **kwargs)

  Evaluate two multipitch (multi-f0) transcriptions, where the first is treated as the reference (ground truth) and the second as the estimate to be evaluated (prediction).

  Parameters:
    ref_time np.ndarray

      Time of each reference frequency value

    ref_freqs list of np.ndarray

      List of np.ndarrays of reference frequency values

    est_time np.ndarray

      Time of each estimated frequency value

    est_freqs list of np.ndarray

      List of np.ndarrays of estimate frequency values

    **kwargs

      Additional keyword arguments which will be passed to the appropriate metric or preprocessing functions.

  Returns:
    scores dict

      Dictionary of scores, where the key is the metric name (str) and the value is the (float) score achieved.

  Examples

      >>> ref_time, ref_freq = mir_eval.io.load_ragged_time_series('ref.txt')
      >>> est_time, est_freq = mir_eval.io.load_ragged_time_series('est.txt')
      >>> scores = mir_eval.multipitch.evaluate(ref_time, ref_freq,
      ...                                       est_time, est_freq)