Source code for mirdata.datasets.rwc_popular

"""RWC Popular Dataset Loader

.. admonition:: Dataset Info
    :class: dropdown

    The Popular Music Database consists of 100 songs — 20 songs with English lyrics
    performed in the style of popular music typical of songs on the American hit
    charts in the 1980s, and 80 songs with Japanese lyrics performed in the style of
    modern Japanese popular music typical of songs on the Japanese hit charts in
    the 1990s.

    For more details, please visit:

import csv
import logging
import os
from typing import BinaryIO, Optional, TextIO, Tuple

import librosa
import numpy as np

from mirdata import download_utils
from mirdata import jams_utils
from mirdata import core
from mirdata import annotations
from mirdata import io

# these functions are identical for all rwc datasets
from mirdata.datasets.rwc_classical import (

BIBTEX = """@inproceedings{goto2002rwc,
  title={RWC Music Database: Popular, Classical and Jazz Music Databases.},
  author={Goto, Masataka and Hashiguchi, Hiroki and Nishimura, Takuichi and Oka, Ryuichi},
  booktitle={3rd International Society for Music Information Retrieval Conference},
  note={Cite this if using audio, beat or section annotations},
  title={A feature smoothing method for chord recognition using recurrence plots},
  author={Cho, Taemin and Bello, Juan P},
  booktitle={12th International Society for Music Information Retrieval Conference},
  note={Cite this if using chord annotations},
  title={Timbre and Melody Features for the Recognition of Vocal Activity and Instrumental Solos in Polyphonic Music.},
  author={Mauch, Matthias and Fujihara, Hiromasa and Yoshii, Kazuyoshi and Goto, Masataka},
  note={Cite this if using vocal-instrumental activity annotations},
    "metadata": download_utils.RemoteFileMetadata(
    "annotations_beat": download_utils.RemoteFileMetadata(
    "annotations_sections": download_utils.RemoteFileMetadata(
    "annotations_chords": download_utils.RemoteFileMetadata(
    "annotations_vocal_act": download_utils.RemoteFileMetadata(
    Unfortunately the audio files of the RWC-Popular dataset are not available
    for download. If you have the RWC-Popular dataset, place the contents into a
    folder called RWC-Popular with the following structure:
        > RWC-Popular/
            > annotations/
            > audio/rwc-p-m0i with i in [1 .. 7]
            > metadata-master/
    and copy the RWC-Popular folder to {}

[docs]class Track(core.Track): """rwc_popular Track class Args: track_id (str): track id of the track Attributes: artist (str): artist audio_path (str): path of the audio file beats_path (str): path of the beat annotation file chords_path (str): path of the chord annotation file drum_information (str): If the drum is 'Drum sequences', 'Live drums', or 'Drum loops' duration (float): Duration of the track in seconds instruments (str): List of used instruments piece_number (str): Piece number, [1-50] sections_path (str): path of the section annotation file singer_information (str): could be male, female or vocal group suffix (str): M01-M04 tempo (str): Tempo of the track in BPM title (str): title track_id (str): track id track_number (str): CD track number voca_inst_path (str): path of the vocal/instrumental annotation file Cached Properties: sections (SectionData): human-labeled section annotation beats (BeatData): human-labeled beat annotation chords (ChordData): human-labeled chord annotation vocal_instrument_activity (EventData): human-labeled vocal/instrument activity """ def __init__( self, track_id, data_home, dataset_name, index, metadata, ): super().__init__( track_id, data_home, dataset_name, index, metadata, ) self.sections_path = self.get_path("sections") self.beats_path = self.get_path("beats") self.chords_path = self.get_path("chords") self.voca_inst_path = self.get_path("voca_inst") self.audio_path = self.get_path("audio") @property def piece_number(self): return self._track_metadata.get("piece_number") @property def suffix(self): return self._track_metadata.get("suffix") @property def track_number(self): return self._track_metadata.get("track_number") @property def title(self): return self._track_metadata.get("title") @property def artist(self): return self._track_metadata.get("artist") @property def singer_information(self): return self._track_metadata.get("singer_information") @property def duration(self): return self._track_metadata.get("duration") @property def tempo(self): return self._track_metadata.get("tempo") @property def instruments(self): return self._track_metadata.get("instruments") @property def drum_information(self): return self._track_metadata.get("drum_information") @core.cached_property def sections(self) -> Optional[annotations.SectionData]: return load_sections(self.sections_path) @core.cached_property def beats(self) -> Optional[annotations.BeatData]: return load_beats(self.beats_path) @core.cached_property def chords(self) -> Optional[annotations.ChordData]: return load_chords(self.chords_path) @core.cached_property def vocal_instrument_activity(self) -> Optional[annotations.EventData]: return load_vocal_activity(self.voca_inst_path) @property def audio(self) -> Optional[Tuple[np.ndarray, float]]: """The track's audio Returns: * np.ndarray - audio signal * float - sample rate """ return load_audio(self.audio_path)
[docs] def to_jams(self): """Get the track's data in jams format Returns: jams.JAMS: the track's data in jams format """ return jams_utils.jams_converter( audio_path=self.audio_path, beat_data=[(, None)], section_data=[(self.sections, None)], chord_data=[(self.chords, None)], metadata=self._track_metadata, )
[docs]@io.coerce_to_string_io def load_chords(fhandle: TextIO) -> annotations.ChordData: """Load rwc chord data from a file Args: fhandle (str or file-like): File-like object or path to chord annotation file Returns: ChordData: chord data """ begs = [] # timestamps of chord beginnings ends = [] # timestamps of chord endings chords = [] # chord labels reader = csv.reader(fhandle, delimiter="\t") for line in reader: begs.append(float(line[0])) ends.append(float(line[1])) chords.append(line[2]) return annotations.ChordData(np.array([begs, ends]).T, chords)
[docs]@io.coerce_to_string_io def load_vocal_activity(fhandle: TextIO) -> annotations.EventData: """Load rwc vocal activity data from a file Args: fhandle (str or file-like): File-like object or path to vocal activity annotation file Returns: EventData: vocal activity data """ begs = [] # timestamps of vocal-instrument activity beginnings ends = [] # timestamps of vocal-instrument activity endings events = [] # vocal-instrument activity labels reader = csv.reader(fhandle, delimiter="\t") raw_data = [] for line in reader: if line[0] != "Piece No.": raw_data.append(line) for i in range(len(raw_data)): # Parsing vocal-instrument activity as intervals (beg, end, event) if raw_data[i] != raw_data[-1]: begs.append(float(raw_data[i][0])) ends.append(float(raw_data[i + 1][0])) events.append(raw_data[i][1]) return annotations.EventData(np.array([begs, ends]).T, events)
[docs]@core.docstring_inherit(core.Dataset) class Dataset(core.Dataset): """ The rwc_popular dataset """ def __init__(self, data_home=None): super().__init__( data_home, name="rwc_popular", track_class=Track, bibtex=BIBTEX, remotes=REMOTES, download_info=DOWNLOAD_INFO, license_info=LICENSE_INFO, ) @core.cached_property def _metadata(self): metadata_path = os.path.join(self.data_home, "metadata-master", "rwc-p.csv") if not os.path.exists(metadata_path): raise FileNotFoundError("Metadata not found. Did you run .download()?") with open(metadata_path, "r") as fhandle: dialect = csv.Sniffer().sniff( reader = csv.reader(fhandle, dialect) raw_data = [] for line in reader: if line[0] != "Piece No.": raw_data.append(line) metadata_index = {} for line in raw_data: if line[0] == "Piece No.": continue p = "00" + line[0].split(".")[1][1:] track_id = "RM-P{}".format(p[len(p) - 3 :]) metadata_index[track_id] = { "piece_number": line[0], "suffix": line[1], "track_number": line[2], "title": line[3], "artist": line[4], "singer_information": line[5], "duration": _duration_to_sec(line[6]), "tempo": line[7], "instruments": line[8], "drum_information": line[9], } return metadata_index
[docs] @core.copy_docs(load_audio) def load_audio(self, *args, **kwargs): return load_audio(*args, **kwargs)
[docs] @core.copy_docs(load_sections) def load_sections(self, *args, **kwargs): return load_sections(*args, **kwargs)
[docs] @core.copy_docs(load_beats) def load_beats(self, *args, **kwargs): return load_beats(*args, **kwargs)
[docs] @core.copy_docs(load_chords) def load_chords(self, *args, **kwargs): return load_chords(*args, **kwargs)
[docs] @core.copy_docs(load_vocal_activity) def load_vocal_activity(self, *args, **kwargs): return load_vocal_activity(*args, **kwargs)