Source code for symusic.soundfont

from dataclasses import dataclass
from hashlib import sha384
from pathlib import Path

from platformdirs import user_data_path
from pySmartDL import SmartDL


[docs] @dataclass(frozen=True) class Soundfont: """Descriptor for a SoundFont artifact (.sf2/.sf3). This lightweight record tracks where to fetch a curated font, how to verify it, and where it is stored locally. It exposes convenience helpers so downstream code can obtain a valid path without duplicating download or integrity logic. """ name: str """Local filename used when saving the SoundFont.""" url: str """Public URL from which the SoundFont can be downloaded.""" hash_: str """SHA-384 digest of the file used to verify integrity after download."""
[docs] def path(self, download: bool = True) -> Path: """Return the local path to the SoundFont file. Parameters ---------- download : bool, default True When True, automatically download the file if it is missing or fails integrity verification. Returns ------- pathlib.Path Absolute path where the SoundFont is stored. """ if download and not self.exists(): self.download() return user_data_path("soundfont", "symusic") / self.name
[docs] def exists(self) -> bool: """Check whether the local SoundFont file exists and matches the hash. Returns ------- bool True if the file exists and its SHA-384 digest matches ``hash_``. """ path = self.path(download=False) if not path.exists(): return False with path.open("rb") as f: return sha384(f.read()).hexdigest() == self.hash_
[docs] def download(self) -> None: """Download the SoundFont file and verify its integrity. The payload is stored under the platform-specific ``platformdirs.user_data_path('soundfont', 'symusic')`` directory. Verification uses the expected SHA-384 digest in ``hash_``. """ # Get path path = self.path(download=False) # Create directory if not exists path.parent.mkdir(parents=True, exist_ok=True) # Download dl = SmartDL(self.url, str(path), threads=8) dl.add_hash_verification("sha384", self.hash_) dl.start() # Check if download is successful if not dl.isSuccessful(): msg = ( f"Failed to download {self.name} to {self.path}. " f"You could try to download it manually from {self.url}, " "and pass the path to the synthesizer." ) raise ConnectionError( msg, )
[docs] class BuiltInSF3: """Curated SoundFont 3 (SF3) presets. Methods return a :class:`Soundfont` descriptor that can be used to download and verify the corresponding asset. """
[docs] @staticmethod def MuseScoreGeneral() -> Soundfont: """MuseScore General (SF3) preset. Returns ------- Soundfont Descriptor for the MuseScore General SF3 asset. """ return Soundfont( name="MuseScore_General.sf3", url="https://ftp.osuosl.org/pub/musescore/soundfont/MuseScore_General/MuseScore_General.sf3", hash_="2c7cefb39fb95f8e9258da215736ea1dc325adad6860a2d7a090a33b47235797086c35e8c962ca4c0654bfa6fde6f28c", )
[docs] class BuiltInSF2: """Curated SoundFont 2 (SF2) presets. Methods return a :class:`Soundfont` descriptor that can be used to download and verify the corresponding asset. """
[docs] @staticmethod def MuseScoreGeneral() -> Soundfont: """MuseScore General (SF2) preset. Returns ------- Soundfont Descriptor for the MuseScore General SF2 asset. """ return Soundfont( name="MuseScore_General.sf2", url="https://ftp.osuosl.org/pub/musescore/soundfont/MuseScore_General/MuseScore_General.sf2", hash_="bcffbd48c829a094b14ade8102ea412cc48018a21081920ea0f3a0b8003c0c1a61cbee988094e094ef7a64236af67504", )