|
"""Utility functions for handling fluidsynth |
|
|
|
""" |
|
|
|
import os |
|
import pkg_resources |
|
|
|
try: |
|
import fluidsynth |
|
_HAS_FLUIDSYNTH = True |
|
except ImportError: |
|
_HAS_FLUIDSYNTH = False |
|
|
|
DEFAULT_SF2 = 'TimGM6mb.sf2' |
|
DEFAULT_SAMPLE_RATE = 44100 |
|
|
|
|
|
def get_fluidsynth_instance(synthesizer=None, sfid=0, fs=None): |
|
""" Check if a valid fluidsynth.Synth instance is provided, and if not, |
|
create one. |
|
|
|
Parameters |
|
---------- |
|
synthesizer : fluidsynth.Synth or str |
|
fluidsynth.Synth instance to use or a string with the path to a .sf2 file. |
|
Default ``None``, which creates a new instance using the TimGM6mb.sf2 file |
|
included with ``pretty_midi``. |
|
sfid : int |
|
Soundfont ID to use if an instance of fluidsynth.Synth is provided. |
|
Default ``0``, which uses the first soundfont. |
|
fs : int |
|
Sampling rate to synthesize at. |
|
Default ``None``, which falls back to ``pretty_midi.fluidsynth.DEFAULT_SAMPLE_RATE`` |
|
= 44100 if a new instance must be created. |
|
If ``synthesizer`` is an existing instance and ``fs`` is specified, then |
|
ValueError will be raised if the sample rates are not equal. |
|
|
|
Returns |
|
------- |
|
synthesizer : fluidsynth.Synth |
|
fluidsynth.Synth instance |
|
sfid : int |
|
Soundfont ID |
|
new_instance_created : bool |
|
Whether a new instance of fluidsynth.Synth was created. |
|
|
|
""" |
|
if not _HAS_FLUIDSYNTH: |
|
raise ImportError("fluidsynth() was called but pyfluidsynth is not installed.") |
|
|
|
if synthesizer is None: |
|
synthesizer = pkg_resources.resource_filename(__name__, DEFAULT_SF2) |
|
|
|
|
|
if isinstance(synthesizer, str): |
|
sf2_path = synthesizer |
|
if not os.path.exists(synthesizer): |
|
raise ValueError("No soundfont file found at the supplied path {}".format(sf2_path)) |
|
fs = fs or DEFAULT_SAMPLE_RATE |
|
synthesizer = fluidsynth.Synth(samplerate=fs) |
|
sfid = synthesizer.sfload(sf2_path) |
|
new_instance_created = True |
|
elif isinstance(synthesizer, fluidsynth.Synth): |
|
synth_fs = synthesizer.get_setting('synth.sample-rate') |
|
if fs and synth_fs != fs: |
|
raise ValueError( |
|
f"synthesizer sample rate of {synth_fs} doesn't match provided fs of {fs}") |
|
new_instance_created = False |
|
else: |
|
raise ValueError("synthesizer must be a str or a fluidsynth.Synth instance") |
|
|
|
return synthesizer, sfid, new_instance_created |
|
|