def _rewrite_meter_( selections, meters, reference_meters=None, rewrite_tuplets=False, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools.topleveltools import mutate meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] reference_meters = reference_meters or () selections = DurationSpellingSpecifier._split_at_measure_boundaries( selections, meters, use_messiaen_style_ties=use_messiaen_style_ties, ) measures = scoretools.make_spacer_skip_measures(durations) staff = scoretools.Staff(measures) mutate(staff).replace_measure_contents(selections) for measure, meter in zip(staff, meters): for reference_meter in reference_meters: if str(reference_meter) == str(meter): meter = reference_meter break mutate(measure[:]).rewrite_meter( meter, rewrite_tuplets=rewrite_tuplets, use_messiaen_style_ties=use_messiaen_style_ties, ) selections = [] for measure in staff: selections.append(measure[:]) return selections
def __or__(self, expr): r'''Logical OR of two payload expressions. Payload expression must be able to fuse. Returns timespan inventory. ''' assert self._can_fuse(expr) if isinstance(self.payload, scoretools.Container): selection = select(self.payload[0], contiguous=True) left = mutate(selection).copy()[0] selection = select(expr.payload[0], contiguous=True) right = mutate(selection).copy()[0] payload = scoretools.Container([left, right]) for component in payload[:]: component._extract() payload = scoretools.Container([payload]) else: payload = self.payload + expr.payload result = type(self)( [], start_offset=self.timespan.start_offset, voice_name=self.voice_name, ) result._payload = payload return timespantools.TimespanInventory([result])
def apply_expressive_marks(score): r'''Applies expressive marks to score. ''' voice = score['First Violin Voice'] markup = markuptools.Markup(r'\left-column { div. \line { con sord. } }', Up) attach(markup, voice[6][1]) markup = markuptools.Markup('sim.', Up) attach(markup, voice[8][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[58][3]) markup = markuptools.Markup('div.', Up) attach(markup, voice[59][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[63][3]) voice = score['Second Violin Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[7][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[66][1]) markup = markuptools.Markup('div.', Up) attach(markup, voice[67][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) voice = score['Viola Voice'] markup = markuptools.Markup('sole', Up) attach(markup, voice[8][0]) voice = score['Cello Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[10][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[84][1]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) voice = score['Bass Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[14][0]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) mutate(voice[88][:]).split( [durationtools.Duration(1, 1), durationtools.Duration(1, 2)]) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[99][1]) strings_staff_group = score['Strings Staff Group'] for voice in iterate(strings_staff_group).by_class(scoretools.Voice): markup = markuptools.Markup(r'\italic { (non dim.) }', Down) attach(markup, voice[102][0])
def to_fixed_multiplier(self): r'''Changes fixed-duration tuplet to (unqualified) tuplet. .. container:: example :: >>> tuplet = scoretools.FixedDurationTuplet((2, 8), []) >>> tuplet.extend("c'8 d'8 e'8") >>> show(tuplet) # doctest: +SKIP :: >>> tuplet FixedDurationTuplet(Duration(1, 4), "c'8 d'8 e'8") :: >>> new_tuplet = tuplet.to_fixed_multiplier() >>> show(new_tuplet) # doctest: +SKIP :: >>> new_tuplet Tuplet(Multiplier(2, 3), "c'8 d'8 e'8") Returns new tuplet. ''' from abjad.tools import scoretools new_tuplet = scoretools.Tuplet(self.multiplier, []) mutate(self).swap(new_tuplet) return new_tuplet
def to_fixed_multiplier(self): r'''Change fixed-duration tuplet to (unqualified) tuplet. .. container:: example :: >>> tuplet = scoretools.FixedDurationTuplet((2, 8), []) >>> tuplet.extend("c'8 d'8 e'8") >>> show(tuplet) # doctest: +SKIP :: >>> tuplet FixedDurationTuplet(Duration(1, 4), "c'8 d'8 e'8") :: >>> new_tuplet = tuplet.to_fixed_multiplier() >>> show(new_tuplet) # doctest: +SKIP :: >>> new_tuplet Tuplet(Multiplier(2, 3), "c'8 d'8 e'8") Returns new tuplet. ''' from abjad.tools import scoretools new_tuplet = scoretools.Tuplet(self.multiplier, []) mutate(self).swap(new_tuplet) return new_tuplet
def apply_expressive_marks(score): r'''Applies expressive marks to score. ''' voice = score['First Violin Voice'] markup = markuptools.Markup( r'\left-column { div. \line { con sord. } }', Up) attach(markup, voice[6][1]) markup = markuptools.Markup('sim.', Up) attach(markup, voice[8][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[58][3]) markup = markuptools.Markup('div.', Up) attach(markup, voice[59][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[63][3]) voice = score['Second Violin Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[7][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[66][1]) markup = markuptools.Markup('div.', Up) attach(markup, voice[67][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) voice = score['Viola Voice'] markup = markuptools.Markup('sole', Up) attach(markup, voice[8][0]) voice = score['Cello Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[10][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[74][0]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[84][1]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) voice = score['Bass Voice'] markup = markuptools.Markup('div.', Up) attach(markup, voice[14][0]) markup = markuptools.Markup(r'\italic { espr. }', Down) attach(markup, voice[86][0]) mutate(voice[88][:]).split( [durationtools.Duration(1, 1), durationtools.Duration(1, 2)] ) markup = markuptools.Markup(r'\italic { molto espr. }', Down) attach(markup, voice[88][1]) markup = markuptools.Markup('uniti', Up) attach(markup, voice[99][1]) strings_staff_group = score['Strings Staff Group'] for voice in iterate(strings_staff_group).by_class(scoretools.Voice): markup = markuptools.Markup(r'\italic { (non dim.) }', Down) attach(markup, voice[102][0])
def _split_at_measure_boundaries( selections, meters, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools.topleveltools import inspect_ from abjad.tools.topleveltools import mutate meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] music = sequencetools.flatten_sequence(selections) assert isinstance(music, list), repr(music) total_duration = sum(durations) music_duration = sum(inspect_(_).get_duration() for _ in music) assert total_duration == music_duration voice = scoretools.Voice(music) mutate(voice[:]).split( durations=durations, tie_split_notes=True, use_messiaen_style_ties=use_messiaen_style_ties, ) selections = list(voice[:]) return selections
def _fuse_tuplets(self): from abjad.tools import scoretools assert self._all_are_contiguous_components_in_same_parent( self, prototype=(scoretools.Tuplet, )) if len(self) == 0: return None first = self[0] first_multiplier = first.multiplier first_type = type(first) for tuplet in self[1:]: if tuplet.multiplier != first_multiplier: message = 'tuplets must carry same multiplier.' raise ValueError(message) if type(tuplet) != first_type: message = 'tuplets must be same type.' raise TypeError(message) if isinstance(first, scoretools.FixedDurationTuplet): total_contents_duration = sum([x._contents_duration for x in self]) new_target_duration = first_multiplier * total_contents_duration new_tuplet = scoretools.FixedDurationTuplet( new_target_duration, []) elif isinstance(first, scoretools.Tuplet): new_tuplet = scoretools.Tuplet(first_multiplier, []) else: message = 'unknown tuplet type.' raise TypeError(message) wrapped = False if self[0]._get_parentage().root is not \ self[-1]._get_parentage().root: dummy_container = scoretools.Container(self) wrapped = True mutate(self).swap(new_tuplet) if wrapped: del (dummy_container[:]) return new_tuplet
def __call__(self, expr): r'''Calls measurewise attack-point optimizer. Returns none. ''' assert isinstance(expr, scoretools.Measure) meter = metertools.Meter(expr) mutate(expr[:]).rewrite_meter( meter, boundary_depth=1, )
def _split_at_measure_boundaries( selections, meters, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools.topleveltools import inspect_ from abjad.tools.topleveltools import mutate from abjad.tools.topleveltools import select meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] selections = sequencetools.flatten_sequence(selections) assert isinstance(selections, list), repr(selections) meter_duration = sum(durations) music_duration = sum(inspect_(_).get_duration() for _ in selections) if not meter_duration == music_duration: message = 'Duration of meters is {!s}' message += ' but duration of selections is {!s}:' message = message.format(meter_duration, music_duration) message += '\nmeters: {}.'.format(meters) message += '\nmusic: {}.'.format(selections) raise Exception(message) voice = scoretools.Voice(selections) mutate(voice[:]).split( durations=durations, tie_split_notes=True, use_messiaen_style_ties=use_messiaen_style_ties, ) #raise Exception(voice) #selections = list(voice[:]) #return selections components = mutate(voice).eject_contents() component_durations = [inspect_(_).get_duration() for _ in components] parts = sequencetools.partition_sequence_by_weights( component_durations, weights=durations, allow_part_weights=Exact, ) part_lengths = [len(_) for _ in parts] parts = sequencetools.partition_sequence_by_counts( components, counts=part_lengths, overhang=Exact, ) selections = [select(_) for _ in parts] return selections
def __call__(self, expr): for i, note in enumerate(iterate(expr).by_class(scoretools.Note)): cluster_width = self.cluster_widths[i] start = note.written_pitch.diatonic_pitch_number diatonic_numbers = range(start, start + cluster_width) chromatic_numbers = [ (12 * (x // 7)) + pitchtools.PitchClass._diatonic_pitch_class_number_to_pitch_class_number[ x % 7] for x in diatonic_numbers ] chord_pitches = [pitchtools.NamedPitch(x) for x in chromatic_numbers] chord = scoretools.Chord(note) chord.note_heads[:] = chord_pitches mutate(note).replace(chord)
def _make_score( self, rhythm_maker, division_list, score_number_markup, ): lists = rhythm_maker(division_list) selections = sequencetools.flatten_sequence(lists) measures = scoretools.make_spacer_skip_measures(division_list) time_signature_context = scoretools.Context( measures, context_name='TimeSignatureContext', name='TimeSignatureContext', ) measures = scoretools.make_spacer_skip_measures(division_list) staff = scoretools.Staff(measures) set_(staff).instrument_name = score_number_markup staff.context_name = 'RhythmicStaff' staff.name = 'Note-entry staff' measures = mutate(staff).replace_measure_contents(selections) score = scoretools.Score() score.append(time_signature_context) score.append(staff) self._add_final_bar_line(score) self._check_score(score) return score
def _make_score( self, rhythm_maker, division_list, score_number_markup, ): lists = rhythm_maker(division_list) music = sequencetools.flatten_sequence(lists) measures = scoretools.make_spacer_skip_measures(division_list) time_signature_context = scoretools.Context( measures, context_name='TimeSignatureContext', name='TimeSignatureContext', ) measures = scoretools.make_spacer_skip_measures(division_list) staff = scoretools.Staff(measures) set_(staff).instrument_name = score_number_markup staff.context_name = 'RhythmicStaff' staff.name = 'Note-entry staff' measures = mutate(staff).replace_measure_contents(music) score = scoretools.Score() score.append(time_signature_context) score.append(staff) self._add_final_bar_line(score) self._check_score(score) return score
def add_string_music_to_score(score): r'''Adds string music to score. ''' # generate some pitch and rhythm information pitch_contour_reservoir = \ abjad.demos.part.create_pitch_contour_reservoir() shadowed_contour_reservoir = \ abjad.demos.part.shadow_pitch_contour_reservoir( pitch_contour_reservoir) durated_reservoir = abjad.demos.part.durate_pitch_contour_reservoir( shadowed_contour_reservoir) # add six dotted-whole notes and the durated contours to each string voice for instrument_name, descents in durated_reservoir.items(): instrument_voice = score['%s Voice' % instrument_name] instrument_voice.extend("R1. R1. R1. R1. R1. R1.") for descent in descents: instrument_voice.extend(descent) # apply instrument-specific edits abjad.demos.part.edit_first_violin_voice(score, durated_reservoir) abjad.demos.part.edit_second_violin_voice(score, durated_reservoir) abjad.demos.part.edit_viola_voice(score, durated_reservoir) abjad.demos.part.edit_cello_voice(score, durated_reservoir) abjad.demos.part.edit_bass_voice(score, durated_reservoir) # chop all string parts into 6/4 measures strings_staff_group = score['Strings Staff Group'] with systemtools.ForbidUpdate(score): for voice in iterate(strings_staff_group).by_class(scoretools.Voice): shards = mutate(voice[:]).split([(6, 4)], cyclic=True) for shard in shards: scoretools.Measure((6, 4), shard)
def edit_second_violin_voice(score, durated_reservoir): r'''Edits second violin voice. ''' voice = score['Second Violin Voice'] descents = durated_reservoir['Second Violin'] last_descent = select(descents[-1]) copied_descent = mutate(last_descent).copy() copied_descent = list(copied_descent) copied_descent[-1].written_duration = durationtools.Duration(1, 1) copied_descent.append(scoretools.Note('a2')) for leaf in copied_descent: articulation = indicatortools.Articulation('accent') attach(articulation, leaf) articulation = indicatortools.Articulation('tenuto') attach(articulation, leaf) voice.extend(copied_descent) final_sustain = [] for _ in range(32): final_sustain.append(scoretools.Note('a1.')) final_sustain.append(scoretools.Note('a2')) articulation = indicatortools.Articulation('accent') attach(articulation, final_sustain[0]) articulation = indicatortools.Articulation('tenuto') attach(articulation, final_sustain[0]) voice.extend(final_sustain) tie = spannertools.Tie() attach(tie, final_sustain) voice.extend('r4 r2.')
def __illustrate__(self): r'''Attempts to illustrate selection. Evaluates the storage format of the selection (to sever any references to the source score from which the selection was taken). Then tries to wrap the result in a staff; in the case that notes of only C4 are found then sets the staff context name to ``'RhythmicStaff'``. If this works then the staff is wrapped in a LilyPond file and the file is returned. If this doesn't work then the method raises an exception. The idea is that the illustration should work for simple selections of that represent an essentially contiguous snippet of a single voice of music. Returns LilyPond file. ''' from abjad.tools import lilypondfiletools from abjad.tools import markuptools from abjad.tools import pitchtools from abjad.tools import scoretools from abjad.tools.topleveltools import mutate music = mutate(self).copy() staff = scoretools.Staff(music) found_different_pitch = False for pitch in pitchtools.list_named_pitches_in_expr(staff): if pitch != pitchtools.NamedPitch("c'"): found_different_pitch = True break if not found_different_pitch: staff.context_name = 'RhythmicStaff' score = scoretools.Score([staff]) lilypond_file = lilypondfiletools.make_basic_lilypond_file(score) lilypond_file.header_block.tagline = markuptools.Markup('""') return lilypond_file
def edit_cello_voice(score, durated_reservoir): r'''Edits cello voice. ''' voice = score['Cello Voice'] descents = durated_reservoir['Cello'] logical_tie = inspect_(voice[-1]).get_logical_tie() for leaf in logical_tie.leaves: parent = leaf._get_parentage().parent index = parent.index(leaf) parent[index] = scoretools.Chord(['e,', 'a,'], leaf.written_duration) selection = voice[-len(descents[-1]):] unison_descent = mutate(selection).copy() voice.extend(unison_descent) for chord in unison_descent: index = inspect_(chord).get_parentage().parent.index(chord) parent[index] = scoretools.Note( chord.written_pitches[1], chord.written_duration) articulation = indicatortools.Articulation('accent') attach(articulation, parent[index]) articulation = indicatortools.Articulation('tenuto') attach(articulation, parent[index]) voice.extend('a,1. ~ a,2') voice.extend('b,1 ~ b,1. ~ b,1.') voice.extend('a,1. ~ a,1. ~ a,1. ~ a,1. ~ a,1. ~ a,2') voice.extend('r4 r2.')
def _notate_leaves( self, grace_handler=None, voice=None, ): for leaf in iterate(voice).by_leaf(): if leaf._has_indicator(indicatortools.Annotation): annotation = leaf._get_indicator(indicatortools.Annotation) pitches, grace_container = grace_handler(annotation.value) if not pitches: new_leaf = scoretools.Rest(leaf) elif 1 < len(pitches): new_leaf = scoretools.Chord(leaf) new_leaf.written_pitches = pitches else: new_leaf = scoretools.Note(leaf) new_leaf.written_pitch = pitches[0] if grace_container: attach(grace_container, new_leaf) tie = spannertools.Tie() if tie._attachment_test(new_leaf): attach(tie, new_leaf) mutate(leaf).replace(new_leaf) else: previous_leaf = leaf._get_leaf(-1) if isinstance(previous_leaf, scoretools.Rest): new_leaf = type(previous_leaf)( leaf.written_duration, ) elif isinstance(previous_leaf, scoretools.Note): new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) else: new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) mutate(leaf).replace(new_leaf) tie = inspect_(previous_leaf).get_spanner(spannertools.Tie) if tie is not None: tie._append(new_leaf) if leaf._has_indicator(indicatortools.Tempo): tempo = leaf._get_indicator(indicatortools.Tempo) detach(indicatortools.Tempo, leaf) attach(tempo, new_leaf)
def _notate_leaves( self, grace_handler=None, voice=None, ): for leaf in voice.select_leaves(): if leaf._has_indicator(indicatortools.Annotation): annotation = leaf._get_indicator(indicatortools.Annotation) pitches, grace_container = grace_handler(annotation.value) if not pitches: new_leaf = scoretools.Rest(leaf) elif 1 < len(pitches): new_leaf = scoretools.Chord(leaf) new_leaf.written_pitches = pitches else: new_leaf = scoretools.Note(leaf) new_leaf.written_pitch = pitches[0] if grace_container: attach(grace_container, new_leaf) tie = spannertools.Tie() if tie._attachment_test(new_leaf): attach(tie, new_leaf) mutate(leaf).replace(new_leaf) else: previous_leaf = leaf._get_leaf(-1) if isinstance(previous_leaf, scoretools.Rest): new_leaf = type(previous_leaf)( leaf.written_duration, ) elif isinstance(previous_leaf, scoretools.Note): new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) else: new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) mutate(leaf).replace(new_leaf) tie = inspect_(previous_leaf).get_spanner(spannertools.Tie) if tie is not None: tie._append(new_leaf) if leaf._has_indicator(indicatortools.Tempo): tempo = leaf._get_indicator(indicatortools.Tempo) detach(indicatortools.Tempo, leaf) attach(tempo, new_leaf)
def from_selections(cls, selections, time_signatures=None): r'''Makes a selection of measures from `selections`. Returns selections. ''' from abjad.tools import scoretools assert len(selections) if not time_signatures: time_signatures = [_.get_duration() for _ in selections] assert len(selections) == len(time_signatures) assert [_.get_duration() for _ in selections] == \ [durationtools.Duration(_) for _ in time_signatures] measures = scoretools.make_spacer_skip_measures(time_signatures) temporary_voice = scoretools.Voice(measures) mutate(temporary_voice).replace_measure_contents(selections) temporary_voice[:] = [] return measures
def _rewrite_rest_filled_tuplets(self, selections): tuplet_spelling_specifier = self._get_tuplet_spelling_specifier() if not tuplet_spelling_specifier.rewrite_rest_filled_tuplets: return selections new_selections = [] for selection in selections: new_selection = [] for component in selection: if not (isinstance(component, scoretools.Tuplet) and component._is_rest_filled): new_selection.append(component) continue duration = inspect_(component).get_duration() new_rests = scoretools.make_rests([duration]) mutate(component[:]).replace(new_rests) new_selection.append(component) new_selection = selectiontools.Selection(new_selection) new_selections.append(new_selection) return new_selections
def _apply_logical_tie_masks(self, selections): from abjad.tools import rhythmmakertools if self.logical_tie_masks is None: return selections # wrap every selection in a temporary container; # this allows the call to mutate().replace() to work containers = [] for selection in selections: container = scoretools.Container(selection) attach('temporary container', container) containers.append(container) logical_ties = iterate(selections).by_logical_tie() logical_ties = list(logical_ties) total_logical_ties = len(logical_ties) for index, logical_tie in enumerate(logical_ties[:]): matching_mask = self.logical_tie_masks.get_matching_pattern( index, total_logical_ties, ) if not isinstance(matching_mask, rhythmmakertools.SilenceMask): continue if isinstance(logical_tie.head, scoretools.Rest): continue for leaf in logical_tie: rest = scoretools.Rest(leaf.written_duration) inspector = inspect_(leaf) if inspector.has_indicator(durationtools.Multiplier): multiplier = inspector.get_indicator( durationtools.Multiplier, ) multiplier = durationtools.Multiplier(multiplier) attach(multiplier, rest) mutate(leaf).replace([rest]) detach(spannertools.Tie, rest) # remove every temporary container and recreate selections new_selections = [] for container in containers: inspector = inspect_(container) assert inspector.get_indicator(str) == 'temporary container' new_selection = mutate(container).eject_contents() new_selections.append(new_selection) return new_selections
def __call__(self, expr): r'''Calls diatonic cluster handler on `expr`. Returns none. ''' for i, note in enumerate(iterate(expr).by_class(scoretools.Note)): cluster_width = self.cluster_widths[i] start = note.written_pitch.diatonic_pitch_number diatonic_numbers = range(start, start + cluster_width) chromatic_numbers = [ (12 * (x // 7)) + pitchtools.PitchClass. _diatonic_pitch_class_number_to_pitch_class_number[x % 7] for x in diatonic_numbers ] chord_pitches = [ pitchtools.NamedPitch(x) for x in chromatic_numbers ] chord = scoretools.Chord(note) chord.note_heads[:] = chord_pitches mutate(note).replace(chord)
def make_lilypond_file(music, divisions, implicit_scaling=False): r'''Makes LilyPond file. .. container:: :: >>> maker = rhythmmakertools.EvenRunRhythmMaker(1) >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> music = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP Used in rhythm-maker docs. Returns LilyPond file. ''' assert isinstance(music, list), repr(music) prototype = (selectiontools.Selection, scoretools.Tuplet) assert all(isinstance(x, prototype) for x in music), repr(music) assert isinstance(divisions, (tuple, list)), repr(divisions) score = scoretools.Score() lilypond_file = \ lilypondfiletools.make_floating_time_signature_lilypond_file(score) context = scoretools.Context(context_name='TimeSignatureContext') measures = scoretools.make_spacer_skip_measures( divisions, implicit_scaling=implicit_scaling, ) context.extend(measures) score.append(context) measures = scoretools.make_spacer_skip_measures( divisions, implicit_scaling=implicit_scaling, ) staff = scoretools.Staff(measures) staff.context_name = 'RhythmicStaff' music = sequencetools.flatten_sequence(music) measures = mutate(staff).replace_measure_contents(music) score.append(staff) return lilypond_file
def _split_payload_at_offsets(self, offsets): assert isinstance(self.payload, scoretools.Container) music = self.payload self._payload = scoretools.Container() shards = mutate([music]).split( offsets, cyclic=False, fracture_spanners=True, ) shards = [shard[0] for shard in shards] for shard in shards: if not inspect_(shard).is_well_formed(): inspect_(shard).tabulate_well_formedness_violations_in_expr() return shards
def __mul__(self, n): r'''Copies component `n` times and detaches spanners. Returns list of new components. ''' from abjad.tools import spannertools result = mutate(self).copy(n=n) for component in iterate(result).by_class(): detach(spannertools.Spanner, component) if isinstance(result, type(self)): result = [result] else: result = list(result) result = selectiontools.Selection(result) return result
def _fuse_tuplets(self): from abjad.tools import scoretools assert self._all_are_contiguous_components_in_same_parent( self, prototype=(scoretools.Tuplet,)) if len(self) == 0: return None first = self[0] first_multiplier = first.multiplier first_type = type(first) for tuplet in self[1:]: if tuplet.multiplier != first_multiplier: message = 'tuplets must carry same multiplier.' raise ValueError(message) if type(tuplet) != first_type: message = 'tuplets must be same type.' raise TypeError(message) if isinstance(first, scoretools.FixedDurationTuplet): total_contents_duration = sum( [x._contents_duration for x in self]) new_target_duration = first_multiplier * total_contents_duration new_tuplet = scoretools.FixedDurationTuplet( new_target_duration, []) elif isinstance(first, scoretools.Tuplet): new_tuplet = scoretools.Tuplet(first_multiplier, []) else: message = 'unknown tuplet type.' raise TypeError(message) wrapped = False if self[0]._get_parentage().root is not \ self[-1]._get_parentage().root: dummy_container = scoretools.Container(self) wrapped = True mutate(self).swap(new_tuplet) if wrapped: del(dummy_container[:]) return new_tuplet
def edit_first_violin_voice(score, durated_reservoir): r'''Edits first violin voice. ''' voice = score['First Violin Voice'] descents = durated_reservoir['First Violin'] descents = selectiontools.Selection(descents) last_descent = select(descents[-1]) copied_descent = mutate(last_descent).copy() voice.extend(copied_descent) final_sustain_rhythm = [(6, 4)] * 43 + [(1, 2)] final_sustain_notes = scoretools.make_notes(["c'"], final_sustain_rhythm) voice.extend(final_sustain_notes) tie = spannertools.Tie() attach(tie, final_sustain_notes) voice.extend('r4 r2.')
def _gallery_input_block_to_score(self, block): from abjad.tools import sequencetools maker = type(self)(**block.input_) lists = maker(block.divisions) music = sequencetools.flatten_sequence(lists) measures = scoretools.make_spacer_skip_measures(block.divisions) time_signature_context = scoretools.Context( measures, context_name='TimeSignatureContext', name='TimeSignatureContext', ) measures = scoretools.make_spacer_skip_measures(block.divisions) staff = scoretools.RhythmicStaff(measures) measures = mutate(staff).replace_measure_contents(music) score = scoretools.Score() score.append(time_signature_context) score.append(staff) return score
def _copy_and_include_enclosing_containers(self): from abjad.tools import scoretools assert self._all_are_contiguous_components_in_same_logical_voice(self) # get governor parentage = self[0]._get_parentage(include_self=True) governor = parentage._get_governor() # find start and stop indices in governor governor_leaves = list(governor.select_leaves()) for i, x in enumerate(governor_leaves): if x is self[0]: start_index_in_governor = i for i, x in enumerate(governor_leaves): if x is self[-1]: stop_index_in_governor = i # copy governor governor_copy = mutate(governor).copy() copied_leaves = governor_copy.select_leaves() # find start and stop leaves in copy of governor start_leaf = copied_leaves[start_index_in_governor] stop_leaf = copied_leaves[stop_index_in_governor] # trim governor copy forwards from first leaf found_start_leaf = False while not found_start_leaf: leaf = next(iterate(governor_copy).by_class(scoretools.Leaf)) if leaf is start_leaf: found_start_leaf = True else: leaf._remove_and_shrink_durated_parent_containers() # trim governor copy backwards from last leaf found_stop_leaf = False while not found_stop_leaf: reverse_iterator = iterate(governor_copy).by_class(scoretools.Leaf, reverse=True) leaf = next(reverse_iterator) if leaf is stop_leaf: found_stop_leaf = True else: leaf._remove_and_shrink_durated_parent_containers() # return trimmed governor copy return governor_copy
def _copy_and_include_enclosing_containers(self): from abjad.tools import scoretools assert self._all_are_contiguous_components_in_same_logical_voice(self) # get governor parentage = self[0]._get_parentage(include_self=True) governor = parentage._get_governor() # find start and stop indices in governor governor_leaves = list(governor.select_leaves()) for i, x in enumerate(governor_leaves): if x is self[0]: start_index_in_governor = i for i, x in enumerate(governor_leaves): if x is self[-1]: stop_index_in_governor = i # copy governor governor_copy = mutate(governor).copy() copied_leaves = governor_copy.select_leaves() # find start and stop leaves in copy of governor start_leaf = copied_leaves[start_index_in_governor] stop_leaf = copied_leaves[stop_index_in_governor] # trim governor copy forwards from first leaf found_start_leaf = False while not found_start_leaf: leaf = next(iterate(governor_copy).by_class(scoretools.Leaf)) if leaf is start_leaf: found_start_leaf = True else: leaf._remove_and_shrink_durated_parent_containers() # trim governor copy backwards from last leaf found_stop_leaf = False while not found_stop_leaf: reverse_iterator = iterate(governor_copy).by_class( scoretools.Leaf, reverse=True) leaf = next(reverse_iterator) if leaf is stop_leaf: found_stop_leaf = True else: leaf._remove_and_shrink_durated_parent_containers() # return trimmed governor copy return governor_copy
def edit_viola_voice(score, durated_reservoir): r'''Edits viola voice. ''' voice = score['Viola Voice'] descents = durated_reservoir['Viola'] for leaf in descents[-1]: articulation = indicatortools.Articulation('accent') attach(articulation, leaf) articulation = indicatortools.Articulation('tenuto') attach(articulation, leaf) last_descent = select(descents[-1]) copied_descent = mutate(last_descent).copy() for leaf in copied_descent: if leaf.written_duration == durationtools.Duration(4, 4): leaf.written_duration = durationtools.Duration(8, 4) else: leaf.written_duration = durationtools.Duration(4, 4) voice.extend(copied_descent) bridge = scoretools.Note('e1') articulation = indicatortools.Articulation('tenuto') attach(articulation, bridge) articulation = indicatortools.Articulation('accent') attach(articulation, bridge) voice.append(bridge) final_sustain_rhythm = [(6, 4)] * 21 + [(1, 2)] final_sustain_notes = scoretools.make_notes(['e'], final_sustain_rhythm) articulation = indicatortools.Articulation('accent') attach(articulation, final_sustain_notes[0]) articulation = indicatortools.Articulation('tenuto') attach(articulation, final_sustain_notes[0]) voice.extend(final_sustain_notes) tie = spannertools.Tie() attach(tie, final_sustain_notes) voice.extend('r4 r2.')
def make_lilypond_file(music, divisions): r'''Makes LilyPond file. .. container:: :: >>> maker = rhythmmakertools.EvenRunRhythmMaker(1) >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> music = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP Used in rhythm-maker docs. Returns LilyPond file. ''' score = scoretools.Score() lilypond_file = \ lilypondfiletools.make_floating_time_signature_lilypond_file(score) context = scoretools.Context(context_name='TimeSignatureContext') measures = scoretools.make_spacer_skip_measures(divisions) context.extend(measures) score.append(context) measures = scoretools.make_spacer_skip_measures(divisions) staff = scoretools.RhythmicStaff(measures) music = sequencetools.flatten_sequence(music) measures = mutate(staff).replace_measure_contents(music) score.append(staff) return lilypond_file
def rotate(self, n, fracture_spanners=True): r'''Rotate start-positioned rhythm payload expression. Example 1. Rotate by count: :: >>> payload = [Container("c'8 d'8 e'8 f'8")] >>> expression = \ ... musicexpressiontools.StartPositionedRhythmPayloadExpression( ... payload, Offset(0)) :: >>> result = expression.rotate(-1) :: >>> print(format(expression)) musicexpressiontools.StartPositionedRhythmPayloadExpression( payload=scoretools.Container( "{ d'8 e'8 f'8 } { c'8 }" ), start_offset=durationtools.Offset(0, 1), ) Example 2. Rotate by duration: :: >>> payload = [Container("c'8 d'8 e'8 f'8")] >>> expression = \ ... musicexpressiontools.StartPositionedRhythmPayloadExpression( ... payload, Offset(0)) :: >>> result = expression.rotate(-Duration(3, 16)) :: >>> print(format(expression)) musicexpressiontools.StartPositionedRhythmPayloadExpression( payload=scoretools.Container( "{ d'16 e'8 f'8 } { c'8 d'16 }" ), start_offset=durationtools.Offset(0, 1), ) Operates in place and returns start-positioned rhythm payload expression. ''' from experimental.tools import musicexpressiontools if isinstance(n, int): leaves = datastructuretools.CyclicTuple(self.payload.select_leaves()) if 0 < n: split_offset = leaves[-n]._get_timespan().start_offset elif n == 0: return self else: split_offset = leaves[-(n+1)]._get_timespan().stop_offset elif isinstance(n, musicexpressiontools.RotationExpression): rotation_expression = n if rotation_expression.level is None: components_at_level = self.payload.select_leaves() else: components_at_level = [] for component in \ iterate(self.payload).by_class(): score_index = component._get_parentage().score_index if len(score_index) == rotation_expression.level: components_at_level.append(component) components_at_level = datastructuretools.CyclicTuple(components_at_level) if isinstance(rotation_expression.index, int): if 0 < rotation_expression.index: split_offset = components_at_level[ -rotation_expression.index]._get_timespan().start_offset elif n == 0: return self else: split_offset = components_at_level[ -(rotation_expression.index+1)]._get_timespan().stop_offset else: index = durationtools.Duration(rotation_expression.index) if 0 <= index: split_offset = self.payload._get_duration() - index else: split_offset = abs(index) if rotation_expression.fracture_spanners is not None: fracture_spanners = rotation_expression.fracture_spanners else: n = durationtools.Duration(n) if 0 <= n: split_offset = self.payload._get_duration() - n else: split_offset = abs(n) #self._debug(split_offset, 'split offset') try: payload_duration = getattr(self, 'payload') except AttributeError: payload_duration = self.payload._get_duration() if split_offset == payload_duration: return self if fracture_spanners: result = mutate([self.payload]).split( [split_offset], cyclic=False, fracture_spanners=True, tie_split_notes=False, ) left_half, right_half = result[0][0], result[-1][0] payload = scoretools.Container() payload.extend(right_half) payload.extend(left_half) assert inspect_(payload).is_well_formed() self._payload = payload else: result = mutate(self.payload[:]).split( [split_offset], cyclic=False, fracture_spanners=False, tie_split_notes=False, ) left_half, right_half = result[0], result[-1] prototype = (spannertools.DuratedComplexBeam, ) descendants = self.payload._get_descendants() for spanner in descendants.get_spanners(prototype): if left_half[-1] in spanner and right_half[0] in spanner: leaf_right_of_split = right_half[0] split_offset_in_beam = spanner._start_offset_in_me( leaf_right_of_split) left_durations, right_durations = \ sequencetools.split_sequence( spanner.durations, [split_offset_in_beam], cyclic=False, overhang=True, ) new_durations = right_durations + left_durations spanner._durations = new_durations new_payload = right_half + left_half self.payload._music = new_payload for component in new_payload: component._update_later(offsets=True) for spanner in self.payload._get_descendants().get_spanners(): spanner._components.sort( key=lambda x: x._get_parentage().score_index ) assert inspect_(self.payload).is_well_formed() return self
def apply_full_measure_tuplets_to_contents_of_measures_in_expr( expr, supplement=None): r'''Applies full-measure tuplets to contents of measures in `expr`: :: >>> staff = Staff([ ... Measure((2, 8), "c'8 d'8"), ... Measure((3, 8), "e'8 f'8 g'8")]) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print format(staff) \new Staff { { \time 2/8 c'8 d'8 } { \time 3/8 e'8 f'8 g'8 } } :: >>> scoretools.apply_full_measure_tuplets_to_contents_of_measures_in_expr(staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print format(staff) \new Staff { { \time 2/8 { c'8 d'8 } } { \time 3/8 { e'8 f'8 g'8 } } } Returns none. ''' from abjad.tools import selectiontools from abjad.tools import scoretools supplement = selectiontools.ContiguousSelection(supplement) assert isinstance(supplement, selectiontools.ContiguousSelection) for measure in iterate(expr).by_class(scoretools.Measure): target_duration = measure._preprolated_duration tuplet = scoretools.FixedDurationTuplet(target_duration, measure[:]) if supplement: new_supplement = mutate(supplement).copy() tuplet.extend(new_supplement)
def recurse( boundary_depth=None, boundary_offsets=None, depth=0, logical_tie=None, ): offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) #print('DEPTH:', depth) logical_tie_duration = logical_tie._preprolated_duration logical_tie_timespan = logical_tie.get_timespan() logical_tie_start_offset = logical_tie_timespan.start_offset logical_tie_stop_offset = logical_tie_timespan.stop_offset logical_tie_starts_in_offsets = logical_tie_start_offset in offsets logical_tie_stops_in_offsets = logical_tie_stop_offset in offsets if not metertools.MeterManager.is_acceptable_logical_tie( logical_tie_duration=logical_tie_duration, logical_tie_starts_in_offsets=logical_tie_starts_in_offsets, logical_tie_stops_in_offsets=logical_tie_stops_in_offsets, maximum_dot_count=maximum_dot_count, ): #print('UNACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) #print('\t', ' '.join([str(x) for x in offsets])) split_offset = None offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) # If the logical tie's start aligns, take the latest possible offset. if logical_tie_starts_in_offsets: offsets = reversed(offsets) for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break #print('\tABS:', split_offset) if split_offset is not None: split_offset -= logical_tie_start_offset #print('\tREL:', split_offset) #print() shards = mutate(logical_tie[:]).split( [split_offset], use_messiaen_style_ties=use_messiaen_style_ties, ) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print() recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth + 1, logical_tie=logical_tie, ) elif metertools.MeterManager.is_boundary_crossing_logical_tie( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, logical_tie_start_offset=logical_tie_start_offset, logical_tie_stop_offset=logical_tie_stop_offset, ): #print('BOUNDARY CROSSING', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) offsets = boundary_offsets if logical_tie_start_offset in boundary_offsets: offsets = reversed(boundary_offsets) split_offset = None for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break assert split_offset is not None #print('\tABS:', split_offset) split_offset -= logical_tie_start_offset #print('\tREL:', split_offset) #print() shards = mutate(logical_tie[:]).split( [split_offset], use_messiaen_style_ties=use_messiaen_style_ties, ) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print('ACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) #print('\t', ' '.join([str(x) for x in offsets])) #print() logical_tie[:]._fuse()
def apply_full_measure_tuplets_to_contents_of_measures_in_expr( expr, supplement=None): r'''Applies full-measure tuplets to contents of measures in `expr`: :: >>> staff = Staff([ ... Measure((2, 8), "c'8 d'8"), ... Measure((3, 8), "e'8 f'8 g'8")]) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { { \time 2/8 c'8 d'8 } { \time 3/8 e'8 f'8 g'8 } } :: >>> scoretools.apply_full_measure_tuplets_to_contents_of_measures_in_expr(staff) >>> show(staff) # doctest: +SKIP .. doctest:: >>> print(format(staff)) \new Staff { { \time 2/8 { c'8 d'8 } } { \time 3/8 { e'8 f'8 g'8 } } } Returns none. ''' from abjad.tools import selectiontools from abjad.tools import scoretools supplement = selectiontools.Selection(supplement) assert isinstance(supplement, selectiontools.Selection) for measure in iterate(expr).by_class(scoretools.Measure): target_duration = measure._preprolated_duration tuplet = scoretools.FixedDurationTuplet(target_duration, measure[:]) if supplement: new_supplement = mutate(supplement).copy() tuplet.extend(new_supplement)
def recurse( boundary_depth=None, boundary_offsets=None, depth=0, logical_tie=None, ): offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) #print 'DEPTH:', depth logical_tie_duration = logical_tie._preprolated_duration logical_tie_timespan = logical_tie.get_timespan() logical_tie_start_offset = logical_tie_timespan.start_offset logical_tie_stop_offset = logical_tie_timespan.stop_offset logical_tie_starts_in_offsets = logical_tie_start_offset in offsets logical_tie_stops_in_offsets = logical_tie_stop_offset in offsets if not metertools.MeterManager.is_acceptable_logical_tie( logical_tie_duration=logical_tie_duration, logical_tie_starts_in_offsets=logical_tie_starts_in_offsets, logical_tie_stops_in_offsets=logical_tie_stops_in_offsets, maximum_dot_count=maximum_dot_count, ): #print 'UNACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset #print '\t', ' '.join([str(x) for x in offsets]) split_offset = None offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) # If the logical tie's start aligns, take the latest possible offset. if logical_tie_starts_in_offsets: offsets = reversed(offsets) for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break #print '\tABS:', split_offset if split_offset is not None: split_offset -= logical_tie_start_offset #print '\tREL:', split_offset #print '' shards = mutate(logical_tie[:]).split([split_offset]) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print '' recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth + 1, logical_tie=logical_tie, ) elif metertools.MeterManager.is_boundary_crossing_logical_tie( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, logical_tie_start_offset=logical_tie_start_offset, logical_tie_stop_offset=logical_tie_stop_offset, ): #print 'BOUNDARY CROSSING', logical_tie, logical_tie_start_offset, logical_tie_stop_offset offsets = boundary_offsets if logical_tie_start_offset in boundary_offsets: offsets = reversed(boundary_offsets) split_offset = None for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break assert split_offset is not None #print '\tABS:', split_offset split_offset -= logical_tie_start_offset #print '\tREL:', split_offset #print '' shards = mutate(logical_tie[:]).split([split_offset]) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print 'ACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset #print '\t', ' '.join([str(x) for x in offsets]) #print '' logical_tie[:]._fuse()
def rotate(self, n, fracture_spanners=True): r'''Rotate start-positioned rhythm payload expression. Example 1. Rotate by count: :: >>> payload = [Container("c'8 d'8 e'8 f'8")] >>> expression = \ ... musicexpressiontools.StartPositionedRhythmPayloadExpression( ... payload, Offset(0)) :: >>> result = expression.rotate(-1) :: >>> print(format(expression)) musicexpressiontools.StartPositionedRhythmPayloadExpression( payload=scoretools.Container( "{ d'8 e'8 f'8 } { c'8 }" ), start_offset=durationtools.Offset(0, 1), ) Example 2. Rotate by duration: :: >>> payload = [Container("c'8 d'8 e'8 f'8")] >>> expression = \ ... musicexpressiontools.StartPositionedRhythmPayloadExpression( ... payload, Offset(0)) :: >>> result = expression.rotate(-Duration(3, 16)) :: >>> print(format(expression)) musicexpressiontools.StartPositionedRhythmPayloadExpression( payload=scoretools.Container( "{ d'16 e'8 f'8 } { c'8 d'16 }" ), start_offset=durationtools.Offset(0, 1), ) Operates in place and returns start-positioned rhythm payload expression. ''' from experimental.tools import musicexpressiontools if isinstance(n, int): leaves = datastructuretools.CyclicTuple( self.payload.select_leaves()) if 0 < n: split_offset = leaves[-n]._get_timespan().start_offset elif n == 0: return self else: split_offset = leaves[-(n + 1)]._get_timespan().stop_offset elif isinstance(n, musicexpressiontools.RotationExpression): rotation_expression = n if rotation_expression.level is None: components_at_level = self.payload.select_leaves() else: components_at_level = [] for component in \ iterate(self.payload).by_class(): score_index = component._get_parentage().score_index if len(score_index) == rotation_expression.level: components_at_level.append(component) components_at_level = datastructuretools.CyclicTuple( components_at_level) if isinstance(rotation_expression.index, int): if 0 < rotation_expression.index: split_offset = components_at_level[-rotation_expression. index]._get_timespan( ).start_offset elif n == 0: return self else: split_offset = components_at_level[-( rotation_expression.index + 1)]._get_timespan().stop_offset else: index = durationtools.Duration(rotation_expression.index) if 0 <= index: split_offset = self.payload._get_duration() - index else: split_offset = abs(index) if rotation_expression.fracture_spanners is not None: fracture_spanners = rotation_expression.fracture_spanners else: n = durationtools.Duration(n) if 0 <= n: split_offset = self.payload._get_duration() - n else: split_offset = abs(n) #self._debug(split_offset, 'split offset') try: payload_duration = getattr(self, 'payload') except AttributeError: payload_duration = self.payload._get_duration() if split_offset == payload_duration: return self if fracture_spanners: result = mutate([self.payload]).split( [split_offset], cyclic=False, fracture_spanners=True, tie_split_notes=False, ) left_half, right_half = result[0][0], result[-1][0] payload = scoretools.Container() payload.extend(right_half) payload.extend(left_half) assert inspect_(payload).is_well_formed() self._payload = payload else: result = mutate(self.payload[:]).split( [split_offset], cyclic=False, fracture_spanners=False, tie_split_notes=False, ) left_half, right_half = result[0], result[-1] prototype = (spannertools.DuratedComplexBeam, ) descendants = self.payload._get_descendants() for spanner in descendants.get_spanners(prototype): if left_half[-1] in spanner and right_half[0] in spanner: leaf_right_of_split = right_half[0] split_offset_in_beam = spanner._start_offset_in_me( leaf_right_of_split) left_durations, right_durations = \ sequencetools.split_sequence( spanner.durations, [split_offset_in_beam], cyclic=False, overhang=True, ) new_durations = right_durations + left_durations spanner._durations = new_durations new_payload = right_half + left_half self.payload._music = new_payload for component in new_payload: component._update_later(offsets=True) for spanner in self.payload._get_descendants().get_spanners(): spanner._components.sort( key=lambda x: x._get_parentage().score_index) assert inspect_(self.payload).is_well_formed() return self
def from_score(score, populate=True): r'''Makes pitch array from `score`. .. container:: example **Example 1.** Makes empty pitch array from score: :: >>> score = Score([]) >>> score.append(Staff("c'8 d'8 e'8 f'8")) >>> score.append(Staff("c'4 d'4")) >>> score.append( ... Staff( ... scoretools.FixedDurationTuplet( ... Duration(2, 8), "c'8 d'8 e'8") * 2)) .. doctest:: >>> print(format(score)) \new Score << \new Staff { c'8 d'8 e'8 f'8 } \new Staff { c'4 d'4 } \new Staff { \times 2/3 { c'8 d'8 e'8 } \times 2/3 { c'8 d'8 e'8 } } >> :: >>> show(score) # doctest: +SKIP :: >>> array = pitchtools.PitchArray.from_score( ... score, populate=False) :: >>> print(array) [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] .. container:: example **Example 2.** Makes populated pitch array from `score`: :: >>> score = Score([]) >>> score.append(Staff("c'8 d'8 e'8 f'8")) >>> score.append(Staff("c'4 d'4")) >>> score.append( ... Staff( ... scoretools.FixedDurationTuplet( ... Duration(2, 8), "c'8 d'8 e'8") * 2)) .. doctest:: >>> print(format(score)) \new Score << \new Staff { c'8 d'8 e'8 f'8 } \new Staff { c'4 d'4 } \new Staff { \times 2/3 { c'8 d'8 e'8 } \times 2/3 { c'8 d'8 e'8 } } >> :: >>> show(score) # doctest: +SKIP :: >>> array = pitchtools.PitchArray.from_score( ... score, populate=True) :: >>> print(array) [c' ] [d' ] [e' ] [f' ] [c' ] [d' ] [c'] [d' ] [e'] [c'] [d' ] [e'] Returns pitch array. ''' from abjad.tools import pitchtools from abjad.tools import scoretools time_intervals = \ PitchArray._get_composite_offset_difference_series_from_leaves_in_expr( score) array_width = len(time_intervals) array_depth = len(score) pitch_array = PitchArray(array_depth, array_width) items = scoretools.make_multiplied_quarter_notes( [0], time_intervals) for leaf_iterable, pitch_array_row in \ zip(score, pitch_array.rows): durations = [] for leaf in iterate(leaf_iterable).by_class(scoretools.Leaf): durations.append(leaf._get_duration()) parts = mutate(items).split( durations, cyclic=False, fracture_spanners=False, ) part_lengths = [len(part) for part in parts] cells = pitch_array_row.cells grouped_cells = sequencetools.partition_sequence_by_counts( cells, part_lengths, cyclic=False, overhang=False, ) for group in grouped_cells: pitch_array_row.merge(group) leaves = iterate(leaf_iterable).by_class(scoretools.Leaf) if populate: for cell, leaf in zip(pitch_array_row.cells, leaves): cell.pitches.extend( pitchtools.list_named_pitches_in_expr(leaf)) return pitch_array
def make_lilypond_file( selections, divisions, implicit_scaling=None, pitched_staff=None, time_signatures=None, ): r'''Makes LilyPond file. .. container:: **Example 1.** :: >>> maker = rhythmmakertools.EvenRunRhythmMaker(exponent=1) >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> selections = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... selections, ... divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP Used in rhythm-maker docs. Returns LilyPond file. ''' assert isinstance(selections, list), repr(selections) prototype = selectiontools.Selection assert all(isinstance(_, prototype) for _ in selections), repr(selections) assert isinstance(divisions, (tuple, list)), repr(divisions) time_signatures = time_signatures or divisions score = scoretools.Score() lilypond_file = \ lilypondfiletools.make_floating_time_signature_lilypond_file(score) context = scoretools.Context(context_name='TimeSignatureContext') measures = scoretools.make_spacer_skip_measures( time_signatures, implicit_scaling=implicit_scaling, ) context.extend(measures) score.append(context) measures = scoretools.make_spacer_skip_measures( time_signatures, implicit_scaling=implicit_scaling, ) if pitched_staff: staff = scoretools.Staff(measures) else: staff = scoretools.Staff(measures, context_name='RhythmicStaff') selections = sequencetools.flatten_sequence(selections) selections_ = copy.deepcopy(selections) try: measures = mutate(staff).replace_measure_contents(selections) except StopIteration: if pitched_staff: staff = scoretools.Staff(selections_) else: staff = scoretools.Staff(selections_, context_name='RhythmicStaff') score.append(staff) return lilypond_file
def to_tuplet( self, proportions, dotted=False, is_diminution=True, ): r'''Change logical tie to tuplet. .. container:: example **Example 1.** Change logical tie to diminished tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.Hairpin(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = TimeSignature((7, 16)) >>> attach(time_signature, staff) .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 ~ \< \p c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> logical_tie = inspect_(staff[0]).get_logical_tie() >>> logical_tie.to_tuplet([2, 1, 1, 1], is_diminution=True) FixedDurationTuplet(Duration(3, 16), "c'8 c'16 c'16 c'16") .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 3/5 { c'8 \< \p c'16 c'16 c'16 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP .. container:: example **Example 2.** Change logical tie to augmented tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.Hairpin(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = TimeSignature((7, 16)) >>> attach(time_signature, staff) .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 ~ \< \p c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> logical_tie = inspect_(staff[0]).get_logical_tie() >>> logical_tie.to_tuplet([2, 1, 1, 1], is_diminution=False) FixedDurationTuplet(Duration(3, 16), "c'16 c'32 c'32 c'32") .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 6/5 { c'16 \< \p c'32 c'32 c'32 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP Returns tuplet. ''' from abjad.tools import scoretools from abjad.tools import mathtools from abjad.tools import spannertools # coerce input proportions = mathtools.Ratio(proportions) # find target duration of fixed-duration tuplet target_duration = self._preprolated_duration # find duration of each note in tuplet prolated_duration = target_duration / sum(proportions) # find written duration of each notes in tuplet if is_diminution: if dotted: basic_written_duration = \ prolated_duration.equal_or_greater_assignable else: basic_written_duration = \ prolated_duration.equal_or_greater_power_of_two else: if dotted: basic_written_duration = \ prolated_duration.equal_or_lesser_assignable else: basic_written_duration = \ prolated_duration.equal_or_lesser_power_of_two # find written duration of each note in tuplet written_durations = [x * basic_written_duration for x in proportions] # make tuplet notes try: notes = [scoretools.Note(0, x) for x in written_durations] except AssignabilityError: denominator = target_duration._denominator note_durations = [durationtools.Duration(x, denominator) for x in proportions] notes = scoretools.make_notes(0, note_durations) # make tuplet tuplet = scoretools.FixedDurationTuplet(target_duration, notes) # replace logical tie with tuplet mutate(self).replace(tuplet) # untie tuplet for spanner in tuplet._get_spanners(spannertools.Tie): spanner._sever_all_components() #detach(spannertools.Tie, tuplet) # return tuplet return tuplet
def to_tuplet( self, proportions, dotted=False, is_diminution=True, ): r'''Change logical tie to tuplet. .. container:: example **Example 1.** Change logical tie to diminished tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.Hairpin(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = TimeSignature((7, 16)) >>> attach(time_signature, staff) .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 ~ \< \p c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> logical_tie = inspect_(staff[0]).get_logical_tie() >>> logical_tie.to_tuplet([2, 1, 1, 1], is_diminution=True) FixedDurationTuplet(Duration(3, 16), "c'8 c'16 c'16 c'16") .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 3/5 { c'8 \< \p c'16 c'16 c'16 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP .. container:: example **Example 2.** Change logical tie to augmented tuplet: :: >>> staff = Staff(r"c'8 ~ c'16 cqs''4") >>> crescendo = spannertools.Hairpin(descriptor='p < f') >>> attach(crescendo, staff[:]) >>> override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = TimeSignature((7, 16)) >>> attach(time_signature, staff) .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 c'8 ~ \< \p c'16 cqs''4 \f } :: >>> show(staff) # doctest: +SKIP :: >>> logical_tie = inspect_(staff[0]).get_logical_tie() >>> logical_tie.to_tuplet([2, 1, 1, 1], is_diminution=False) FixedDurationTuplet(Duration(3, 16), "c'16 c'32 c'32 c'32") .. doctest:: >>> print(format(staff)) \new Staff \with { \override DynamicLineSpanner #'staff-padding = #3 } { \time 7/16 \tweak #'text #tuplet-number::calc-fraction-text \times 6/5 { c'16 \< \p c'32 c'32 c'32 } cqs''4 \f } :: >>> show(staff) # doctest: +SKIP Returns tuplet. ''' from abjad.tools import scoretools from abjad.tools import mathtools from abjad.tools import agenttools from abjad.tools import scoretools from abjad.tools import spannertools from abjad.tools import scoretools # coerce input proportions = mathtools.Ratio(proportions) # find target duration of fixed-duration tuplet target_duration = self._preprolated_duration # find duration of each note in tuplet prolated_duration = target_duration / sum(proportions) # find written duration of each notes in tuplet if is_diminution: if dotted: basic_written_duration = \ prolated_duration.equal_or_greater_assignable else: basic_written_duration = \ prolated_duration.equal_or_greater_power_of_two else: if dotted: basic_written_duration = \ prolated_duration.equal_or_lesser_assignable else: basic_written_duration = \ prolated_duration.equal_or_lesser_power_of_two # find written duration of each note in tuplet written_durations = [x * basic_written_duration for x in proportions] # make tuplet notes try: notes = [scoretools.Note(0, x) for x in written_durations] except AssignabilityError: denominator = target_duration._denominator note_durations = [durationtools.Duration(x, denominator) for x in proportions] notes = scoretools.make_notes(0, note_durations) # make tuplet tuplet = scoretools.FixedDurationTuplet(target_duration, notes) # replace logical tie with tuplet mutate(self).replace(tuplet) # untie tuplet for spanner in tuplet._get_spanners(spannertools.Tie): spanner._sever_all_components() #detach(spannertools.Tie, tuplet) # return tuplet return tuplet