atsushieee's picture
Upload folder using huggingface_hub
b9df2e0 verified
"""Configuration module for audio settings and chord progressions."""
from dataclasses import dataclass, field
from pathlib import Path
import yaml
@dataclass
class PitchDetectorConfig:
"""Configuration settings for pitch detection."""
sample_rate: int = 16000
hop_length: int = 512
decoder_mode: str = "local_argmax"
threshold: float = 0.006
f0_min: int = 80
f0_max: int = 880
interp_uv: bool = False
device: str = "cpu"
@dataclass
class AudioConfig:
"""Configuration class for audio-related settings."""
sample_rate: int = 16000
buffer_duration: float = 0.3
note_duration: float = 1.0
pitch_detector: PitchDetectorConfig = field(default_factory=PitchDetectorConfig)
@classmethod
def from_yaml(cls, yaml_data: dict) -> "AudioConfig":
"""Create AudioConfig instance from YAML data."""
config = cls(
sample_rate=yaml_data.get("sample_rate", cls.sample_rate),
buffer_duration=yaml_data.get("buffer_duration", cls.buffer_duration),
note_duration=yaml_data.get("note_duration", cls.note_duration),
)
if "pitch_detector" in yaml_data:
pitch_detector_data = yaml_data["pitch_detector"]
# The sample rate must be set explicitly
# Use the sample rate specified in the audio config
pitch_detector_data["sample_rate"] = config.sample_rate
config.pitch_detector = PitchDetectorConfig(**pitch_detector_data)
return config
@dataclass
class IntervalPracticeConfig:
"""Configuration settings for interval practice."""
num_problems: int = 10
interval: int = 0
@classmethod
def from_yaml(cls, yaml_data: dict) -> "IntervalPracticeConfig":
"""Create IntervalPracticeConfig instance from YAML data."""
return cls(
num_problems=yaml_data.get("num_problems", cls.num_problems),
interval=yaml_data.get("interval", cls.interval),
)
@dataclass
class PiecePracticeConfig:
"""Configuration settings for piece practice."""
selected_song: str = "fly_me_to_the_moon"
chord_progressions: dict = field(default_factory=dict)
@classmethod
def from_yaml(cls, yaml_data: dict) -> "PiecePracticeConfig":
"""Create PiecePracticeConfig instance from YAML data."""
return cls(
selected_song=yaml_data.get("selected_song", cls.selected_song),
chord_progressions=yaml_data.get(
"chord_progressions", {cls.selected_song: []}
),
)
@dataclass
class Config:
"""Application configuration handler."""
audio: AudioConfig
interval_practice: IntervalPracticeConfig
piece_practice: PiecePracticeConfig
def __init__(self, config_path: str | Path = "config.yml"):
"""Initialize Config instance.
Args:
config_path: Path to YAML configuration file (default: 'config.yml').
"""
self.config_path = Path(config_path)
self._load_config()
def _load_config(self):
if self.config_path.exists():
with open(self.config_path, "r") as f:
yaml_data = yaml.safe_load(f)
self.audio = AudioConfig.from_yaml(yaml_data.get("audio", {}))
self.interval_practice = IntervalPracticeConfig.from_yaml(
yaml_data.get("interval_practice", {})
)
self.piece_practice = PiecePracticeConfig.from_yaml(
yaml_data.get("piece_practice", {})
)
else:
self.audio = AudioConfig()
self.interval_practice = IntervalPracticeConfig()
self.piece_practice = PiecePracticeConfig()
self.piece_practice.chord_progressions = {
# opening 4 bars of Fly Me to the Moon
"fly_me_to_the_moon": [
("A", "natural_minor", "A", "min7", 8),
("A", "natural_minor", "D", "min7", 8),
("C", "major", "G", "dom7", 8),
("C", "major", "C", "maj7", 4),
("F", "major", "C", "dom7", 4),
]
}