Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add loader for candombe_beat_downbeat #553

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/source/mirdata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ billboard
:inherited-members:


candombe
^^^^^^^^

.. automodule:: mirdata.datasets.candombe
:members:
:inherited-members:


cante100
^^^^^^^^

Expand Down
8 changes: 8 additions & 0 deletions docs/source/table.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@
- .. image:: https://licensebuttons.net/l/zero/1.0/80x15.png
:target: http://creativecommons.org/publicdomain/zero/1.0/

* - Candombe
- - audio: ✅
- annotations: ✅
- - :ref:`beats`
- 35
- .. image:: https://licensebuttons.net/l/by-nc-sa/4.0/80x15.png
:target: https://creativecommons.org/licenses/by-nc-sa/4.0

* - cante100
- - audio: 🔑
- annotations: ✅
Expand Down
177 changes: 177 additions & 0 deletions mirdata/datasets/candombe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
"""Candombe Dataset Loader

.. admonition:: Dataset Info
:class: dropdown

This is a dataset of Candombe recordings with annotated beats and downbeats, totaling over 2 hours of audio.
It comprises 35 complete performances by renowned players, in groups of three to five drums.
Recording sessions were conducted in studio, in the context of musicological research over the past two decades.
A total of 26 tambor players took part, belonging to different generations and representing all the important traditional Candombe styles.
The audio files are stereo with a sampling rate of 44.1 kHz and 16-bit precision.
The location of beats and downbeats was annotated by an expert, adding to more than 4700 downbeats.

The audio is provided as .flac files and the annotations as .csv files.
The values in the first column of the csv file are the time instants of the beats.
The numbers on the second column indicate both the bar number and the beat number within the bar.
For instance, 1.1, 1.2, 1.3 and 1.4 are the four beats of the first bar. Hence, each label ending with .1 indicates a downbeat.
Another set of annotations are provided as .beats files in which the bar numbers are removed.

"""
import csv
from typing import BinaryIO, Optional, TextIO, Tuple

import librosa
import numpy as np

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

BIBTEX = """
@inproceedings{Nunes2015,
author = {Leonardo Nunes and Martín Rocamora and Luis Jure and Luiz W. P. Biscainho},
title = {{Beat and Downbeat Tracking Based on Rhythmic Patterns Applied to the Uruguayan Candombe Drumming}},
booktitle = {Proceedings of the 16th International Society for Music Information Retrieval Conference (ISMIR 2015)},
month = {Oct.},
address = {Málaga, Spain},
pages = {264--270},
year = {2015}
}
"""

INDEXES = {
"default": "1.0",
"test": "1.0",
"1.0": core.Index(filename="candombe_index_1.0.json"),
}


REMOTES = {
"annotations": download_utils.RemoteFileMetadata(
filename="candombe_annotations.zip",
url="https://zenodo.org/record/6533068/files/candombe_annotations.zip",
checksum="f78aff60aa413cb4960c0c77cc31c243",
destination_dir=None,
),
"audio": download_utils.RemoteFileMetadata(
filename="candombe_audio.zip",
url="https://zenodo.org/record/6533068/files/candombe_audio.zip",
checksum="ccd7f437024807b1a52c0818aa0b7f06",
destination_dir=None,
),
}

LICENSE_INFO = """
Creative Commons Attribution 4.0 International
"""


class Track(core.Track):
"""candombe track class
# -- YOU CAN AUTOMATICALLY GENERATE THIS DOCSTRING BY CALLING THE SCRIPT:
# -- `scripts/print_track_docstring.py my_dataset`
# -- note that you'll first need to have a test track (see "Adding tests to your dataset" below)

Args:
track_id (str): track id of the track

Attributes:
audio_path (str): path to audio file
annotation_path (str): path to annotation file
# -- Add any of the dataset specific attributes here

Cached Properties:
annotation (EventData): a description of this annotation

"""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You would need to update the docstring here, with the attributes and cached properties of your Track class. You would need to basically include audio and beats path as attributes, then beats as cached property.


def __init__(self, track_id, data_home, dataset_name, index, metadata):
super().__init__(track_id, data_home, dataset_name, index, metadata)

self.audio_path = self.get_path("audio")
self.beats_path = self.get_path("beats")

@core.cached_property
def beats(self) -> Optional[annotations.BeatData]:
"""The track's beats

Returns:
BeatData: loaded beat data

"""
return load_beats(self.beats_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)

def to_jams(self):
"""Jams: the track's data in jams format"""
return jams_utils.jams_converter(
audio_path=self.audio_path, beat_data=[(self.beats, None)], metadata=None
)


@io.coerce_to_bytes_io
def load_audio(fhandle: BinaryIO) -> Tuple[np.ndarray, float]:
"""Load a candombe audio file.

Args:
fhandle (str or file-like): path or file-like object pointing to an audio file

Returns:
* np.ndarray - the audio signal
* float - The sample rate of the audio file

"""
return librosa.load(fhandle, sr=None, mono=True)


@io.coerce_to_string_io
def load_beats(fhandle: TextIO) -> annotations.BeatData:
"""Load a candombe beats file.

Args:
fhandle (str or file-like): path or file-like object pointing to an audio file

Returns:
* BeatData: loaded beat data


"""
reader = csv.reader(fhandle, delimiter=",")
times = []
beats = []
for line in reader:
times.append(float(line[0]))
beats.append(int(line[1].split(".")[1]))

beat_data = annotations.BeatData(
times=np.array(times),
time_unit="s",
positions=np.array(beats),
position_unit="bar_index",
)
return beat_data


@core.docstring_inherit(core.Dataset)
class Dataset(core.Dataset):
"""The candombe dataset"""

def __init__(self, data_home=None, version="default"):
super().__init__(
data_home,
version,
name="candombe",
track_class=Track,
bibtex=BIBTEX,
indexes=INDEXES,
remotes=REMOTES,
license_info=LICENSE_INFO,
)
Loading
Loading