"""Denote — Portal and facade for audio-to-symbol tools.
Simple usage::
import denote
result = denote.transcribe("song.wav") # audio -> MIDI
chords = denote.get_chords("song.wav") # audio -> chord labels
pitch = denote.get_pitch("vocal.wav") # audio -> F0
beats = denote.get_beats("song.wav") # audio -> beat times
denote.list_backends() # see what's available
denote.list_backends('pitch') # backends for a task
Service-level access::
denote.services.basic_pitch.transcribe("song.wav", onset_threshold=0.3)
denote.services.torchcrepe.get_pitch("vocal.wav", model='tiny')
Native adapter access::
denote.services.basic_pitch.adapter # raw adapter instance
"""
from denote.base import (
AudioInput,
NoteEvent,
TranscriptionResult,
PitchResult,
ChordResult,
BeatResult,
TASKS,
)
from denote.registry import (
list_backends,
get_default_backend,
register_backend,
get_config,
)
from denote.services import ServiceCollection
# Lazy singleton for service-level access
services = ServiceCollection()
[docs]
def transcribe(audio, *, sr=None, backend=None, **kwargs):
"""Transcribe audio to MIDI.
Args:
audio: File path (str/Path) or numpy array.
sr: Sample rate (required when audio is an array).
backend: Backend name. Defaults to 'basic_pitch' if installed.
**kwargs: Backend-specific parameters (onset_threshold, min_note_length, etc.)
Returns:
TranscriptionResult with .midi, .notes, and .raw fields.
"""
backend = backend or get_default_backend('transcribe')
handle = services[backend]
return handle.transcribe(audio, sr=sr, **kwargs)
[docs]
def get_pitch(audio, *, sr=None, backend=None, **kwargs):
"""Estimate pitch/F0 from audio.
Args:
audio: File path (str/Path) or numpy array.
sr: Sample rate (required when audio is an array).
backend: Backend name. Defaults to 'torchcrepe' if installed,
falls back to 'librosa_pyin'.
**kwargs: Backend-specific parameters (min_frequency, max_frequency,
model, device, hop_length).
Returns:
PitchResult with .times, .frequencies, .confidence fields.
"""
backend = backend or get_default_backend('pitch')
handle = services[backend]
return handle.get_pitch(audio, sr=sr, **kwargs)
[docs]
def get_chords(audio, *, sr=None, backend=None, **kwargs):
"""Recognize chords from audio.
Args:
audio: File path (str/Path) or numpy array.
sr: Sample rate (required when audio is an array).
backend: Backend name.
**kwargs: Backend-specific parameters.
Returns:
ChordResult with .intervals, .labels fields.
"""
backend = backend or get_default_backend('chords')
handle = services[backend]
return handle.get_chords(audio, sr=sr, **kwargs)
[docs]
def get_beats(audio, *, sr=None, backend=None, **kwargs):
"""Track beats in audio.
Args:
audio: File path (str/Path) or numpy array.
sr: Sample rate (required when audio is an array).
backend: Backend name. Defaults to 'librosa_beats'.
**kwargs: Backend-specific parameters (hop_length, start_bpm).
Returns:
BeatResult with .beats, .downbeats, .tempo fields.
"""
backend = backend or get_default_backend('beats')
handle = services[backend]
return handle.get_beats(audio, sr=sr, **kwargs)