How to use the scamp.settings.playback_settings function in scamp

To help you get started, we’ve selected a few scamp examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github MarcTheSpark / scamp / scamp / playback_implementations.py View on Github external
def __init__(self, host_instrument: 'instruments_module.ScampInstrument', midi_output_device: str = "default",
                 num_channels=8, midi_output_name: Optional[str] = None, max_pitch_bend: int = "default",
                 note_on_and_off_only: bool = False):
        super().__init__(host_instrument, num_channels, note_on_and_off_only)

        # we hold onto these arguments for the purposes of json serialization
        # note that if the midi_output_device or midi_output_name said "default",
        # then we save it as "default", rather than what that default resolved to.
        self.num_channels = num_channels
        self.midi_output_device = midi_output_device
        self.midi_output_name = midi_output_name

        midi_output_device = playback_settings.default_midi_output_device if midi_output_device == "default" \
            else midi_output_device
        if midi_output_name is None:
            # if no midi output name is given, fall back to the instrument name
            # if the instrument has no name, fall back to "Unnamed"
            midi_output_name = "Unnamed" if host_instrument.name is None else host_instrument.name

        # since rtmidi can only have 16 output channels, we need to create several output devices if we are using more
        if num_channels <= 16:
            self.rt_simple_outs = [SimpleRtMidiOut(midi_output_device, midi_output_name)]
        else:
            self.rt_simple_outs = [
                SimpleRtMidiOut(midi_output_device, midi_output_name + " chans {}-{}".format(chan, chan + 15))
                for chan in range(0, num_channels, 16)
            ]

        self.max_pitch_bend = None
github MarcTheSpark / scamp / scamp / playback_implementations.py View on Github external
def __init__(self, host_instrument: 'instruments_module.ScampInstrument', bank_and_preset: Tuple[int, int] = (0, 0),
                 soundfont: str = "default", num_channels: int = 8, audio_driver: str = "default",
                 max_pitch_bend: int = "default", note_on_and_off_only: bool = False):
        super().__init__(host_instrument, num_channels, note_on_and_off_only)

        # we hold onto these arguments for the purposes of json serialization
        # note that if the audio_driver said "default", then we save it as "default",
        # rather than what that default resolved to.
        self.audio_driver = audio_driver
        self.bank_and_preset = bank_and_preset

        self.max_pitch_bend = max_pitch_bend
        self.soundfont = playback_settings.default_soundfont if soundfont == "default" else soundfont
        # these are setup by the `_initialize_shared_resources` function
        self.soundfont_host = self.soundfont_instrument = None
github MarcTheSpark / scamp / scamp / _dependencies.py View on Github external
from .settings import playback_settings
import logging
import os
import platform

ABJAD_MINIMUM_VERSION = "3.1"


try:
    if playback_settings.try_system_fluidsynth_first:
        # first choice: import using an installed version of pyfluidsynth
        logging.debug("Trying to load system copy of pyfluidsynth.")
        import fluidsynth
    else:
        # first choice: use the use the local, tweaked copy of pyfluidsynth (which will also try to
        # load up a local copy of the fluidsynth dll on Windows or dylib on MacOS)
        logging.debug("Trying to copy of pyfluidsynth from within SCAMP package.")
        from ._thirdparty import fluidsynth
    logging.debug("Loading of pyfluidsynth succeeded.")
except (ImportError, AttributeError):
    logging.debug("Loading of pyfluidsynth failed.")
    try:
        if playback_settings.try_system_fluidsynth_first:
            # second choice: use the use the local, tweaked copy of pyfluidsynth (which will also try to
            # load up a local copy of the fluidsynth dll on Windows or dylib on MacOS)
            logging.debug("Trying to copy of pyfluidsynth from within SCAMP package.")
github MarcTheSpark / scamp / scamp / _dependencies.py View on Github external
logging.debug("Loading of pyfluidsynth succeeded.")
    except (ImportError, AttributeError):
        # if we're here, it's probably because fluidsynth wasn't installed
        logging.debug("Loading of pyfluidsynth failed again.")
        fluidsynth = None
        logging.warning("Fluidsynth could not be loaded; synth output will not be available.")

if fluidsynth is not None and playback_settings.default_audio_driver == "auto":
    print("Testing for working audio driver...")
    found_driver = False
    for driver in ['alsa', 'coreaudio', 'dsound', 'Direct Sound', 'oss', 'pulseaudio', 'jack', 'portaudio', 'sndmgr']:
        test_synth = fluidsynth.Synth()
        test_synth.start(driver=driver)
        if test_synth.audio_driver is not None:
            playback_settings.default_audio_driver = driver
            playback_settings.make_persistent()
            found_driver = True
            test_synth.delete()
            print("Found audio driver '{}'. This has been made the default, but it can be altered via "
                  "the playback settings.".format(driver))
            break
        test_synth.delete()
    if not found_driver:
        logging.warning("No working audio driver was found; synth output will not be available.")

try:
    from sf2utils.sf2parse import Sf2File
except ImportError:
    Sf2File = None
    logging.warning("sf2utils was not found; info about soundfont presets will not be available.")

try:
github MarcTheSpark / scamp / scamp / _soundfont_host.py View on Github external
def resolve_soundfont_path(soundfont: str):
    """
    Consults playback settings and returns the path to the given soundfont

    :param soundfont: either the name of a named soundfont or an explicit soundfont path. Paths are resolved relatively
    unless they start with a slash.
    :return: an absolute path to the soundfont
    """
    soundfont_path = playback_settings.named_soundfonts[soundfont] \
        if soundfont in playback_settings.named_soundfonts else soundfont

    if soundfont_path.startswith("/"):
        # Absolute soundfont path
        return soundfont_path
    elif soundfont_path.startswith("~/"):
        # Relative to user home directory
        return os.path.expanduser(soundfont_path)
    else:
        # Relative to one of the search paths defined in the settings
        for search_path in playback_settings.soundfont_search_paths:
            if search_path.startswith("~/"):
                search_path = os.path.expanduser(search_path)
            if not search_path.startswith("/"):
                search_path = resolve_relative_path(search_path)
github MarcTheSpark / scamp / scamp / _dependencies.py View on Github external
try:
    if playback_settings.try_system_fluidsynth_first:
        # first choice: import using an installed version of pyfluidsynth
        logging.debug("Trying to load system copy of pyfluidsynth.")
        import fluidsynth
    else:
        # first choice: use the use the local, tweaked copy of pyfluidsynth (which will also try to
        # load up a local copy of the fluidsynth dll on Windows or dylib on MacOS)
        logging.debug("Trying to copy of pyfluidsynth from within SCAMP package.")
        from ._thirdparty import fluidsynth
    logging.debug("Loading of pyfluidsynth succeeded.")
except (ImportError, AttributeError):
    logging.debug("Loading of pyfluidsynth failed.")
    try:
        if playback_settings.try_system_fluidsynth_first:
            # second choice: use the use the local, tweaked copy of pyfluidsynth (which will also try to
            # load up a local copy of the fluidsynth dll on Windows or dylib on MacOS)
            logging.debug("Trying to copy of pyfluidsynth from within SCAMP package.")
            from ._thirdparty import fluidsynth
        else:
            # second choice: import using an installed version of pyfluidsynth
            logging.debug("Trying to load system copy of pyfluidsynth.")
            import fluidsynth
        logging.debug("Loading of pyfluidsynth succeeded.")
    except (ImportError, AttributeError):
        # if we're here, it's probably because fluidsynth wasn't installed
        logging.debug("Loading of pyfluidsynth failed again.")
        fluidsynth = None
        logging.warning("Fluidsynth could not be loaded; synth output will not be available.")

if fluidsynth is not None and playback_settings.default_audio_driver == "auto":
github MarcTheSpark / scamp / scamp / _soundfont_host.py View on Github external
def get_soundfont_presets(which_soundfont="default"):
    which_soundfont = playback_settings.default_soundfont if which_soundfont == "default" else which_soundfont

    soundfont_path = resolve_soundfont_path(which_soundfont)

    if Sf2File is None:
        raise ModuleNotFoundError("Cannot inspect soundfont presets; please install sf2utils.")

    # if we have sf2utils, load up the preset info from the soundfonts
    with open(soundfont_path, "rb") as sf2_file:
        sf2 = Sf2File(sf2_file)
        return sf2.presets
github MarcTheSpark / scamp / scamp / playback_implementations.py View on Github external
def __init__(self, host_instrument: 'instruments_module.ScampInstrument', port: int, ip_address: str = "127.0.0.1",
                 message_prefix: Optional[str] = None, osc_message_addresses: dict = "default"):
        super().__init__(host_instrument)
        # the output client for OSC messages
        # by default the IP address is the local 127.0.0.1
        self.ip_address = ip_address
        self.port = port

        self.client = pythonosc.udp_client.SimpleUDPClient(ip_address, port)
        # the first part of the osc message; used to distinguish between instruments
        # by default uses the name of the instrument with spaces removed
        self.message_prefix = message_prefix if message_prefix is not None \
            else (self._host_instrument.name.replace(" ", "") if self._host_instrument.name is not None else "unnamed")

        self.osc_message_addresses = playback_settings.osc_message_addresses
        if osc_message_addresses != "default":
            assert isinstance(osc_message_addresses, dict), "osc_message_addresses argument must be a complete or " \
                                                            "incomplete dictionary of alternate osc messages"
            # for each type of osc message, use the one specified in the osc_message_addresses argument if available,
            # falling back to the one in playback_settings if it's not available
            self.osc_message_addresses = {key: osc_message_addresses[key] if key in osc_message_addresses else value
                                          for key, value in playback_settings.osc_message_addresses.items()}

        self._currently_playing = []

        def clean_up():
            for note_id in list(self._currently_playing):
                self.end_note(note_id)

        atexit.register(clean_up)
github MarcTheSpark / scamp / scamp / _soundfont_host.py View on Github external
def __init__(self, soundfonts=(), audio_driver="default"):
        """
        A SoundfontHost hosts an instance of fluidsynth with one or several soundfonts loaded.
        It can be called upon to add or remove instruments from that synth

        :param soundfonts: one or several soundfonts to be loaded
        :param audio_driver: the audio driver to use
        """
        if isinstance(soundfonts, str):
            soundfonts = (soundfonts, )

        if fluidsynth is None:
            raise ModuleNotFoundError("FluidSynth not available.")

        self.audio_driver = playback_settings.default_audio_driver if audio_driver == "default" else audio_driver

        self.synth = fluidsynth.Synth()
        self.synth.start(driver=self.audio_driver)

        self.used_channels = 0  # how many channels have we already assigned to various instruments

        self.soundfont_ids = OrderedDict()  # mapping from soundfont names to the fluidsynth ids of loaded soundfonts
        self.soundfont_instrument_lists = {}

        for soundfont in soundfonts:
            self.load_soundfont(soundfont)
github MarcTheSpark / scamp / scamp / _note_properties.py View on Github external
length_segments = length
            length = sum(length)
        else:
            length_segments = None

        did_an_adjustment = False
        # first apply all of the explicit playback adjustments
        for adjustment in self.playback_adjustments:
            assert isinstance(adjustment, NotePlaybackAdjustment)
            pitch, volume, length = adjustment.adjust_parameters(pitch, volume, length)
            did_an_adjustment = True

        if include_notation_derived:
            for notation_category in ["articulations", "noteheads", "notations"]:
                for applied_notation in self[notation_category]:
                    notation_derived_adjustment = playback_settings.adjustments.get(applied_notation)
                    if notation_derived_adjustment is not None:
                        assert isinstance(notation_derived_adjustment, NotePlaybackAdjustment)
                        pitch, volume, length = notation_derived_adjustment.adjust_parameters(pitch, volume, length)
                        did_an_adjustment = True

        # Having made the adjustment, if the length was a tuple of adjoined segments, we now go back
        # and scale those according to the adjustment made to length
        if length_segments is not None:
            length_scale_factor = length / sum(length_segments)
            length = length_segments if length_scale_factor == 1 else \
                tuple(segment_length * length_scale_factor for segment_length in length_segments)

        return pitch, volume, length, did_an_adjustment