Beispiel #1
0
def _make_audio_signal_from_stem(filename, stem, i, sr, label):
    """
    Reads in a :param:`stem` from the stempeg library (`stempeg.read_stems()`) and creates a
    correctly formatted :class:`AudioSignal` object (with all the metadata set up).
    Args:
        filename (str): Name of the file on disc.
        stem (:obj:`np.ndarray`): Numpy array from the `stempeg.read_stems()` function.
        i (int): Index of the :param:`stem: array to get audio data from.
        sr (int): Sample rate.
        label (str): Label for the :class:`AudioSignal` object.

    Returns:
        (:obj:`AudioSignal`) Correctly formatted :class:`AudioSignal` object with the
            right metadata.

    """
    signal = AudioSignal(audio_data_array=stem[i,...], sample_rate=sr)
    signal.path_to_input_file = filename
    signal.label = label
    return signal
Beispiel #2
0
def mir1k(directory, check_hash=True, subset=None, shuffle=False, seed=None, undivided=False):
    """
    Generator function for the MIR-1K data set. This allows you to loop through the entire data set
    with only a few :class:`AudioSignal` objects stored in memory at a time. There are options for
    only looping through a subset of the data set and shuffling the data set (with a seed). See
    details about those options below.

    `nussl` calculates the hash of the MIR-1K directory and compares it against a precomputed hash
    for MIR-1K that ships with `nussl`. This hash is used to verify that `nussl` understands the
    directory structure when reading the files. Calculating the hash can be turned off if the
    user needs a speed up, but this might cause oblique errors if the MIR-1K directory is not set up
    in the same way as a fresh download of MIR-1K.

    MIR-1K also ships with two 'sets' of audio files: the divided and undivided sets. They contain
    the same content, the only difference is that the undivided set is one file per song, each song
    taking up the whole file, and the divided set has the same song divided into segments of ~3-12
    seconds. The :param:`undivided` parameter controls which of these two sets `nussl` will loop
    through.

    Examples:
        Using this generator function to loop through the MIR-1K data set. In this example, we use
        the generator directly in the ``for`` loop.

        .. code-block:: python
            :linenos:

            mir1k_path = '/path/to/MIR-1K'  # the MIR-1K directory in disc
            for mix, vox, acc in nussl.datasets.mir1k(mir1k_path):
                mix.to_mono(overwrite=True)  # sum to mono to make a 'mixture'

                # Get some basic metadata on the files.
                # (They'll all have the same file name, but different labels)
                print('Mixture       - Filename: {}, Label: {}'.format(mix.file_name, mix.label))
                print('Vocals        - Filename: {}, Label: {}'.format(vox.file_name, vox.label))
                print('Accompaniment - Filename: {}, Label: {}'.format(acc.file_name, acc.label))

                # Run an algorithm on the MIR-1K files and save to disc
                r = nussl.Repet(mix)
                r.run()
                bg_est, fg_est = r.make_audio_signals()
                bg_est.write_audio_to_file('{}_bg.wav'.format(os.path.splitext(mix.file_name)[0]))
                fg_est.write_audio_to_file('{}_fg.wav'.format(os.path.splitext(mix.file_name)[0]))

        It's also possible to use ``tqdm`` to print the progress to the console. This is useful
        because running through an entire data set can take a while. Here's a more advanced example
        using some other options as well:

        .. code-block:: python
            :linenos:

            import nussl
            import tdqm

            mir1k_path = 'path/to/MIR-1K' # the MIR-1K directory on disc
            idxs = range(29, 150)[::2]  # Only get every other song between [29, 150)
            mir1k_gen = nussl.datasets.mir1k(mir1k_path, subset=idxs,
                                             check_hash=False, undivided=True)

            # Tell tqdm the number of files we're running on so it can estimate a completion time
            for mixture, vocals, accompaniment in tqdm(mir1k_gen, total=len(idxs)):
                mix.to_mono(overwrite=True)  # sum to mono to make a 'mixture'

                # Run an algorithm on the MIR-1K files and save to disc
                r = nussl.Repet(mix)
                r.run()
                bg_est, fg_est = r.make_audio_signals()
                bg_est.write_audio_to_file('{}_bg.wav'.format(os.path.splitext(mix.file_name)[0]))
                fg_est.write_audio_to_file('{}_fg.wav'.format(os.path.splitext(mix.file_name)[0]))

    Args:
        directory (str): Top-level directory for the MIR-1K data set.
        check_hash (bool, str): In the case that there is a mismatch between the expected and
        calculated hash, if this parameter is ``True`` (a bool) an exception is raised and
        if this parameter is ``'warn'`` (a string) a warning is printed to the console. If
        this parameter is ``False``, the hash will not be calculated for this directory, i.e.,
        this function does nothing.
        subset (float, list, str, None): This parameter determines how to make a subset of the
        audio files in the data set. There are four ways to use it, depending on what type
        this parameter takes:
        1) If :param:`subset` is a ``float``, then :param:`subset` will return the first
        ``X.Y%`` of audio files, where ``X.Y%`` is some arbitrary percentage. In this case,
        :param:`subset` is expected to be in the range [0.0, 1.0].
        2) If :param:`subset` is a ``list``, it is expected to be a list of indices (as
        ``int``s). This function will then produce the audio files in the list that correspond
        to those indices.
        3) If :param:`subset` is a ``str``, it will only include audio files with that string
        somewhere in the directory name.
        4) If :param:`subset` is ``None``, then the whole data set is traversed unobstructed.
        shuffle (bool): Whether the data set should be shuffled.
        seed (int, 1-d array_like): Seed for ``numpy``'s random number generator used for
        shuffling.
        undivided (bool): Whether to use the divided (in the ``Wavefile`` directory) or undivided
        (in the ``UndividedWavefile`` directory).

    Yields:
        (``tuple(AudioSignal, AudioSignal, AudioSignal)``):
            A tuple of three :class:`AudioSignal` objects, with audio loaded for each source. In
            the tuple, they are returned in the following order:
            ``(mixture, vocals, accompaniment)``. In MIR-1K, the audio files are such that the
            vocals are hard panned to one channel and the accompaniment is hard panned to the other.
            So, the 'mixture' yielded here by this function reflects this, and needs to 'mixed'
            down to mono. In other words, ``mixture`` is a stereo :class:`AudioSignal` object,
            where each channel is on source, and similarly ``vocals`` and ``accompaniment`` are
            mono :class:`AudioSignal` objects made from a single channel in `mixture`.

    """

    top_dir_name = 'MIR-1K'

    wavfile_hash = '33c085c1a7028199cd20317868849b413e0971022ebc4aefcf1bbc5516646c29'
    undivided_hash = '3f39af9be17515e042a7005b4c47110c6738623a7fada6233ba104535b7dde1b'

    if undivided:
        audio_dir_name = 'UndividedWavfile'
        mir1k_hash = undivided_hash
    else:
        audio_dir_name = 'Wavfile'
        mir1k_hash = wavfile_hash

    audio_extension = '.wav'
    all_wav_files = _data_set_setup(directory, top_dir_name, audio_dir_name,
                                    mir1k_hash, check_hash, audio_extension)

    all_wav_files = _subset_and_shuffle(all_wav_files, subset, shuffle, seed)

    for f in all_wav_files:
        mixture = AudioSignal(f)
        mixture.label = 'mixture'

        vocals = mixture.make_audio_signal_from_channel(1)
        vocals.label = 'vocals'

        accompaniment = mixture.make_audio_signal_from_channel(0)
        accompaniment.label = 'accompaniment'

        yield mixture, vocals, accompaniment