saysynth.core.font
The Font class creates a list of Notes
within a scale and writes them to separate files. This makes them easy to import into samplers or DAWs.
1""" 2The Font class creates a list of `Notes` within a scale and writes them to separate files. This makes them easy to import into samplers or DAWs. 3<center><img src="/assets/img/sun-wavy.png"></img></center> 4""" 5import os 6from typing import Union 7 8from midi_utils import midi_scale, midi_to_note, note_to_midi 9 10from .note import Note 11 12 13class Font(object): 14 def __init__( 15 self, 16 key: Union[str, int], 17 scale: str, 18 scale_start_at: Union[int, str], 19 scale_end_at: Union[int, str], 20 **note_options, 21 ): 22 """ 23 The Font class creates a list of `Notes` within a 24 scale and writes them to separate files. This 25 makes them easy to import into samplers or DAWs. 26 Scale generation is provided by `midi_scale` 27 Args: 28 key: The root note of the scale, eg: C,D,G#,etc 29 scale: The name of the scale (see midi_utils.constants.SCALES) 30 scale_start_at: A note name or midi note number to start the scale at 31 scale_end_at: A note name or midi note number to end the scale at 32 **note_options: Additional options to pass to `Note` generation. 33 """ 34 # add note type to simplify function call 35 self.scale = midi_scale( 36 key=key, 37 scale=scale, 38 min_note=note_to_midi(scale_start_at), 39 max_note=note_to_midi(scale_end_at), 40 ) 41 note_options.setdefault("type", "note") 42 self.note_options = note_options 43 44 def _get_kwargs(self, midi, kwargs) -> dict: 45 kw = dict(self.note_options) 46 kw.update(kwargs) 47 kw["type"] = "note" 48 kw["midi"] = midi 49 kw["note"] = midi_to_note(midi) 50 return kw 51 52 def play(self, **kwargs) -> None: 53 """ 54 Alias of `self.generate` 55 """ 56 return self.generate(**kwargs) 57 58 def generate(self, **kwargs) -> None: 59 # generate files for each note in the scale 60 if not os.path.exists(kwargs["output_dir"]): 61 os.makedirs(kwargs["output_dir"], exist_ok=True) 62 for midi in self.scale: 63 kwargs = self._get_kwargs(midi, kwargs) 64 65 # generate audio output file name 66 filepath = ( 67 f"{midi:03d}_{kwargs['note']}_" 68 f"{kwargs['voice'].lower()}_{kwargs['rate']}.{kwargs['format']}" 69 ) 70 audio_output_file = os.path.join( 71 kwargs["output_dir"], 72 filepath, 73 ) 74 # generate input file of text 75 note = Note(**kwargs) 76 note.play( 77 voice=kwargs["voice"], 78 rate=kwargs["rate"], 79 audio_output_file=audio_output_file, 80 wait=True, 81 ) 82 if not os.path.exists(audio_output_file): 83 raise RuntimeError( 84 f"File {audio_output_file} was not successfully created" 85 )
class
Font:
14class Font(object): 15 def __init__( 16 self, 17 key: Union[str, int], 18 scale: str, 19 scale_start_at: Union[int, str], 20 scale_end_at: Union[int, str], 21 **note_options, 22 ): 23 """ 24 The Font class creates a list of `Notes` within a 25 scale and writes them to separate files. This 26 makes them easy to import into samplers or DAWs. 27 Scale generation is provided by `midi_scale` 28 Args: 29 key: The root note of the scale, eg: C,D,G#,etc 30 scale: The name of the scale (see midi_utils.constants.SCALES) 31 scale_start_at: A note name or midi note number to start the scale at 32 scale_end_at: A note name or midi note number to end the scale at 33 **note_options: Additional options to pass to `Note` generation. 34 """ 35 # add note type to simplify function call 36 self.scale = midi_scale( 37 key=key, 38 scale=scale, 39 min_note=note_to_midi(scale_start_at), 40 max_note=note_to_midi(scale_end_at), 41 ) 42 note_options.setdefault("type", "note") 43 self.note_options = note_options 44 45 def _get_kwargs(self, midi, kwargs) -> dict: 46 kw = dict(self.note_options) 47 kw.update(kwargs) 48 kw["type"] = "note" 49 kw["midi"] = midi 50 kw["note"] = midi_to_note(midi) 51 return kw 52 53 def play(self, **kwargs) -> None: 54 """ 55 Alias of `self.generate` 56 """ 57 return self.generate(**kwargs) 58 59 def generate(self, **kwargs) -> None: 60 # generate files for each note in the scale 61 if not os.path.exists(kwargs["output_dir"]): 62 os.makedirs(kwargs["output_dir"], exist_ok=True) 63 for midi in self.scale: 64 kwargs = self._get_kwargs(midi, kwargs) 65 66 # generate audio output file name 67 filepath = ( 68 f"{midi:03d}_{kwargs['note']}_" 69 f"{kwargs['voice'].lower()}_{kwargs['rate']}.{kwargs['format']}" 70 ) 71 audio_output_file = os.path.join( 72 kwargs["output_dir"], 73 filepath, 74 ) 75 # generate input file of text 76 note = Note(**kwargs) 77 note.play( 78 voice=kwargs["voice"], 79 rate=kwargs["rate"], 80 audio_output_file=audio_output_file, 81 wait=True, 82 ) 83 if not os.path.exists(audio_output_file): 84 raise RuntimeError( 85 f"File {audio_output_file} was not successfully created" 86 )
Font( key: Union[str, int], scale: str, scale_start_at: Union[int, str], scale_end_at: Union[int, str], **note_options)
15 def __init__( 16 self, 17 key: Union[str, int], 18 scale: str, 19 scale_start_at: Union[int, str], 20 scale_end_at: Union[int, str], 21 **note_options, 22 ): 23 """ 24 The Font class creates a list of `Notes` within a 25 scale and writes them to separate files. This 26 makes them easy to import into samplers or DAWs. 27 Scale generation is provided by `midi_scale` 28 Args: 29 key: The root note of the scale, eg: C,D,G#,etc 30 scale: The name of the scale (see midi_utils.constants.SCALES) 31 scale_start_at: A note name or midi note number to start the scale at 32 scale_end_at: A note name or midi note number to end the scale at 33 **note_options: Additional options to pass to `Note` generation. 34 """ 35 # add note type to simplify function call 36 self.scale = midi_scale( 37 key=key, 38 scale=scale, 39 min_note=note_to_midi(scale_start_at), 40 max_note=note_to_midi(scale_end_at), 41 ) 42 note_options.setdefault("type", "note") 43 self.note_options = note_options
The Font class creates a list of Notes
within a
scale and writes them to separate files. This
makes them easy to import into samplers or DAWs.
Scale generation is provided by midi_scale
Arguments:
- key: The root note of the scale, eg: C,D,G#,etc
- scale: The name of the scale (see midi_utils.constants.SCALES)
- scale_start_at: A note name or midi note number to start the scale at
- scale_end_at: A note name or midi note number to end the scale at
- **note_options: Additional options to pass to
Note
generation.
def
play(self, **kwargs) -> None:
53 def play(self, **kwargs) -> None: 54 """ 55 Alias of `self.generate` 56 """ 57 return self.generate(**kwargs)
Alias of self.generate
def
generate(self, **kwargs) -> None:
59 def generate(self, **kwargs) -> None: 60 # generate files for each note in the scale 61 if not os.path.exists(kwargs["output_dir"]): 62 os.makedirs(kwargs["output_dir"], exist_ok=True) 63 for midi in self.scale: 64 kwargs = self._get_kwargs(midi, kwargs) 65 66 # generate audio output file name 67 filepath = ( 68 f"{midi:03d}_{kwargs['note']}_" 69 f"{kwargs['voice'].lower()}_{kwargs['rate']}.{kwargs['format']}" 70 ) 71 audio_output_file = os.path.join( 72 kwargs["output_dir"], 73 filepath, 74 ) 75 # generate input file of text 76 note = Note(**kwargs) 77 note.play( 78 voice=kwargs["voice"], 79 rate=kwargs["rate"], 80 audio_output_file=audio_output_file, 81 wait=True, 82 ) 83 if not os.path.exists(audio_output_file): 84 raise RuntimeError( 85 f"File {audio_output_file} was not successfully created" 86 )