File size: 2,526 Bytes
9965bf6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
"""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)

    # Create a fluidsynth instance if one wasn't provided
    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