Example #1
0
    def __sub__(self, expr):
        '''Offset taken from offset returns duration:

        ::

            >>> durationtools.Offset(2) - durationtools.Offset(1, 2)
            Duration(3, 2)

        Duration taken from offset returns another offset:

        ::

            >>> durationtools.Offset(2) - durationtools.Duration(1, 2)
            Offset(3, 2)

        Coerce `expr` to offset when `expr` is neither offset nor duration:

        ::

            >>> durationtools.Offset(2) - Fraction(1, 2)
            Duration(3, 2)

        Returns duration or offset.
        '''
        if isinstance(expr, type(self)):
            return Duration(Duration.__sub__(self, expr))
        elif isinstance(expr, Duration):
            return Duration.__sub__(self, expr)
        else:
            expr = type(self)(expr)
            return self - expr
    def test_state_hashing(self):
        note = HashableNote(NamedPitch("A3"), Duration(1, 4))
        duplicate_note = HashableNote(NamedPitch("A3"), Duration(1, 4))
        state = CompositionState(Duration(0), (note, duplicate_note), None)
        duplicate_state = CompositionState(Duration(0), (duplicate_note, note), None)

        self.assertEqual(state, duplicate_state)
        self.assertEqual(hash(state), hash(duplicate_state))
    def test_action_hashing(self):
        note = HashableNote(NamedPitch("A3"), Duration(1, 4))
        duplicate_note = HashableNote(NamedPitch("A3"), Duration(1, 4))
        action = CompositionAction((note, duplicate_note))
        duplicate_action = CompositionAction((duplicate_note, note))

        self.assertEqual(action, duplicate_action)
        self.assertEqual(hash(action), hash(duplicate_action))
Example #4
0
    def __mul__(self, *args):
        r'''Multiplier times duration gives duration.

        Returns duration.
        '''
        if len(args) == 1 and type(args[0]) is Duration:
            return Duration(Duration.__mul__(self, *args))
        else:
            return Duration.__mul__(self, *args)
Example #5
0
    def __mul__(self, *args):
        r'''Multiplier times duration gives duration.

        Returns duration.
        '''
        if len(args) == 1 and type(args[0]) is Duration:
            return Duration(Duration.__mul__(self, *args))
        else:
            return Duration.__mul__(self, *args)
    def test_state_value_function(self):
        state = CompositionState(Duration(0), (self.allowed_note, None), None)
        state_two = CompositionState(Duration(0),
                                     (self.allowed_note, self.allowed_note),
                                     None)
        self.assertEqual(
            0.0, self.value_function.actionvalue(state, self.allowed_action))
        self.value_function.setactionvalue(state, self.allowed_action, 1.0)
        self.assertEqual(
            1.0, self.value_function.actionvalue(state, self.allowed_action))

        self.assertEqual(
            0.0, self.value_function.actionvalue(state_two,
                                                 self.allowed_action))
Example #7
0
 def __new__(class_, *args, **kwargs):
     grace_displacement = None
     for arg in args:
         if hasattr(arg, 'grace_displacement'):
             grace_displacement = getattr(arg, 'grace_displacement')
             break
     grace_displacement = grace_displacement or kwargs.get(
         'grace_displacement')
     if grace_displacement is not None:
         grace_displacement = Duration(grace_displacement)
     grace_displacement = grace_displacement or None
     if len(args) == 1 and isinstance(args[0], Duration):
         args = args[0].pair
     self = Duration.__new__(class_, *args)
     self._grace_displacement = grace_displacement
     return self
    def _generate_actions(self):
        possible_pitches_per_voice = []
        for name, voice_range in self.composition_parameters.desired_voices:
            pitch_set = self.composition_parameters.scale.create_named_pitch_set_in_pitch_range(
                voice_range)
            possible_pitches_per_voice.append(pitch_set)

        possible_durations_per_voice = [[Duration(4, 4)] for _ in range(
            self.composition_parameters.number_of_voices_to_generate)]
        actions = []

        notes_per_voice = []
        for i in range(
                self.composition_parameters.number_of_voices_to_generate):
            notes_per_voice.append([])
            for pitch, duration in itertools.product(
                    possible_pitches_per_voice[i],
                    possible_durations_per_voice[i]):
                notes_per_voice[i].append(HashableNote(pitch, duration))

        index_to_action = dict()
        action_to_index = dict()
        i = 0
        for notes in itertools.product(*notes_per_voice):
            action = CompositionAction(notes)
            actions.append(action)
            index_to_action[i] = action
            action_to_index[action] = i
            i += 1
        return actions, index_to_action, action_to_index
Example #9
0
 def generate_environment() -> Tuple[Domain, Task]:
     composition_parameters = CompositionParameters(
         [("contrapuntal", soprano_range),
          ("cantus", tenor_range)], meter, scale, Duration(11))
     domain = CompositionEnvironment(composition_parameters,
                                     history_length=history_length,
                                     position_invariant=position_invariant)
     task = task_class(domain)
     return domain, task
Example #10
0
 def reward(self, state, action, state_prime):
     if not self.differential:
         if state_prime.preceding_duration == Duration(11):
             return self.grade_composition(self.domain)
         else:
             return 0
     if self.prev_duration == state_prime.preceding_duration:
         assert False
         return
     elif self.prev_duration < state_prime.preceding_duration:
         new_grade = self.grade_composition(self.domain)
         reward = new_grade - self.prev_grade
         self.prev_grade = new_grade
     elif self.prev_duration > state_prime.preceding_duration:
         # This should only be the first step
         reward = self.grade_composition(self.domain)
         self.prev_grade = reward
     self.prev_duration = state_prime.preceding_duration
     return reward
    def __init__(self,
                 composition_parameters: CompositionParameters,
                 given_voices: List[Voice] = list(),
                 history_length=1,
                 position_invariant=False):
        self.given_voices = given_voices
        self.composition_parameters = composition_parameters
        self.history_length = history_length

        self.voices = [
            Voice("", name=name)
            for name, pitch_range in self.composition_parameters.desired_voices
        ]
        self.current_duration = Duration(0)

        actionslist, index_to_action, action_to_index = self._generate_actions(
        )
        self.actions = actionslist
        self.index_to_action = index_to_action
        self.action_to_index = action_to_index
        self.position_invariant = position_invariant
def save_composition(name: str, agent_name: str, composition: CompositionEnvironment, out_dir: str):
    score = Score()
    staff_group = scoretools.StaffGroup([], context_name='StaffGroup')

    for voice in composition.voices + composition.given_voices:
        staff = Staff([voice])
        if voice.name == "cantus":
            attach(Clef("alto"), staff)
        attach(composition.composition_parameters.scale.key_signature, staff)

        staff_group.append(staff)
    tempo = Tempo(Duration(4, 4), 60)
    attach(tempo, staff_group[0])
    score.append(staff_group)
    score.add_final_bar_line()

    lilypond_file = lilypondfiletools.make_basic_lilypond_file(score)
    lilypond_file.header_block.composer = markuptools.Markup(agent_name)
    lilypond_file.header_block.title = markuptools.Markup(name)
    lilypond_file.header_block.tagline = markuptools.Markup()

    midi_block = lilypondfiletools.Block(name="midi")
    context_block = lilypondfiletools.Block(name="context")
    channel_mapping = lilypondfiletools.Block(name="score")

    # channel_mapping.midiChannelMapping = "instrument"
    # context_block.items.append(channel_mapping)
    # midi_block.items.append(context_block)

    lilypond_file.score_block.items.append(midi_block)
    layout_block = lilypondfiletools.Block(name="layout")
    lilypond_file.score_block.items.append(layout_block)

    filename = name + ".ly"
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)
    out_path = os.path.join(out_dir, filename)
    with open(out_path, mode="w") as f:
        f.write(format(lilypond_file))
Example #13
0
 def __init__(self, domain: CompositionEnvironment, differential: bool = True):
     super().__init__(domain)
     self.domain = domain
     self.differential = differential
     self.prev_duration = Duration(0)
     self.prev_grade = 0.0
Example #14
0
    def __gt__(self, arg):
        r'''Is true when offset is greater than `arg`.
        Otherwise false.

        ..  container:: example

            **Example 1.** With equal numerators, denominators and grace
            displacements:

            ::

                >>> offset_1 = Offset((1, 4), grace_displacement=(-1, 16))
                >>> offset_2 = Offset((1, 4), grace_displacement=(-1, 16))

            ::

                >>> offset_1 > offset_1
                False
                >>> offset_1 > offset_2
                False
                >>> offset_2 > offset_1
                False
                >>> offset_2 > offset_2
                False

        ..  container:: example

            **Example 2.** With equal numerators and denominators but differing
            grace displacements:

            ::

                >>> offset_1 = Offset((1, 4), grace_displacement=(-1, 8))
                >>> offset_2 = Offset((1, 4), grace_displacement=(-1, 16))

            ::

                >>> offset_1 > offset_1
                False
                >>> offset_1 > offset_2
                False
                >>> offset_2 > offset_1
                True
                >>> offset_2 > offset_2
                False

        ..  container:: example

            **Example 3.** With differing numerators and denominators. Ignores
            grace displacements:

            ::

                >>> offset_1 = Offset((1, 4))
                >>> offset_2 = Offset((1, 2), grace_displacement=(-99))

            ::

                >>> offset_1 > offset_1
                False
                >>> offset_1 > offset_2
                False
                >>> offset_2 > offset_1
                True
                >>> offset_2 > offset_2
                False

        Returns true or false.
        '''
        if isinstance(arg, type(self)) and self.pair == arg.pair:
            return self._get_grace_displacement() > \
                arg._get_grace_displacement()
        return Duration.__gt__(self, arg)
 def setUp(self):
     self.allowed_note = HashableNote(NamedPitch("A3"), Duration(1, 4))
     self.allowed_action = CompositionAction(
         (self.allowed_note, self.allowed_note))
     self.value_function = StateActionValueTable(
         actions=[self.allowed_action])
    def test_hashable_note_hashing(self):
        note = HashableNote(NamedPitch("A3"), Duration(1, 4))
        duplicate_note = HashableNote(NamedPitch("A3"), Duration(1, 4))

        self.assertEqual(note, duplicate_note)
        self.assertEqual(hash(note), hash(duplicate_note))
 def reset(self):
     self.voices = [
         Voice("") for _ in range(
             self.composition_parameters.number_of_voices_to_generate)
     ]
     self.current_duration = Duration(0)