def __create_chord_on_diatonic_without_type(self, diatonic_tone): from tonalmodel.tonality import Tonality from tonalmodel.modality import ModalityType from harmonicmodel.tertian_chord_template import TertianChordTemplate diatonic_tonality = Tonality.create(ModalityType.Major, diatonic_tone) tone_scale = diatonic_tonality.annotation self.chord_basis = [] base_tone = None for i in range(0, 3): tone = tone_scale[(2 * i) % (len(tone_scale) - 1)] if i == 0: base_tone = tone pitch_a = DiatonicPitch(1, diatonic_tone) b_octave = 2 if base_tone.diatonic_index > tone.diatonic_index else 1 pitch_b = DiatonicPitch(b_octave, tone.diatonic_symbol) interval = Interval.create_interval(pitch_a, pitch_b) self.chord_basis.append(interval) self.__tones.append((tone, interval)) self.__set_inversion() self.__chord_type = TertianChordTemplate.get_chord_type( self.chord_basis)
def test_simple_fixed_pitch(self): logging.debug('Start test_simple_fixed_pitch') note = Note(DiatonicPitch.parse("C:5"), Duration(1, 4)) select_notes = {'A:5', 'C:4', 'Eb:2', 'F#:6'} constraint = FixedPitchSelectSetConstraint( note, {DiatonicPitch.parse(p) for p in select_notes}) policy_context = TestFixedPitchSelectSetConstraint.policy_creator( ModalityType.Major, DiatonicTone('C'), 'tIV', 'C:2', 'C:8') lower_contextual = ContextualNote(policy_context) p_map = PMap() p_map[note] = lower_contextual v_results = constraint.values(p_map, note) assert v_results is not None assert len(v_results) == len(select_notes) for result in v_results: print(str(result)) assert select_notes == {str(n.diatonic_pitch) for n in v_results} assert not constraint.verify(p_map) lower_contextual.note = Note(DiatonicPitch.parse('Eb:2'), Duration(1, 4)) assert constraint.verify(p_map)
def test_across_tonalities(self): logging.debug('Start test_across_tonalities.') lower_policy_context_1 = TestRelativeDiatonicConstraint.policy_creator( ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') lower_policy_context_2 = TestRelativeDiatonicConstraint.policy_creator( ModalityType.Major, DiatonicTone('Ab'), 'tI', 'C:2', 'C:8') upper_note_1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8)) upper_note_2 = Note(DiatonicPitch.parse('D:5'), Duration(1, 8)) lower_note_1 = ContextualNote( lower_policy_context_1, Note(DiatonicPitch.parse('F#:5'), Duration(1, 8))) lower_note_2 = ContextualNote(lower_policy_context_2) p_map = dict([(upper_note_1, lower_note_1), (upper_note_2, lower_note_2)]) policy = RelativeDiatonicConstraint(upper_note_1, upper_note_2, Interval(3, IntervalType.Minor), Interval(3, IntervalType.Major)) v_result = policy.values(p_map, upper_note_2) for note in v_result: logging.debug(note) pitches = [note.diatonic_pitch for note in v_result] assert {str(p) for p in pitches} == {'Eb:5', 'F:5', 'G:5', 'Ab:5'} logging.debug('End test_across_tonalities.')
def test_book_example(self): print('----- book_example -----') voice_line = Line() melody_line = Line() melody_1 = Line( [Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'aceg']) melody_2 = Line( [Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'cadg']) base_line = Line( [Note(DiatonicPitch(4, y), Duration(1, 4)) for y in 'dddddddd']) melody_line.pin(melody_1, Offset(1, 8)) melody_line.pin(melody_2, Offset(1, 4)) voice_line.pin(melody_line) voice_line.pin(base_line) print(voice_line) all_notes = voice_line.get_all_notes() print('... pinned notes ...') for n in all_notes: print('({0}) : {1}'.format(n.get_absolute_position(), n.diatonic_pitch)) print('... end pinned notes ...') print('End test_pin')
def test_is_equal(self): logging.debug('Start test_is_equal') note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8)) note2 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8)) lower_policy_context = TestEqualPitchConstraint.policy_creator( ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') lower_context_note_a = ContextualNote( lower_policy_context, Note(DiatonicPitch.parse('F#:6'), Duration(1, 8))) lower_context_note_b = ContextualNote(lower_policy_context) parameter_map = dict([(note1, lower_context_note_a), (note2, lower_context_note_b)]) parameter_map = PMap(parameter_map) policy = EqualPitchConstraint([note1, note2]) result = policy.values(parameter_map, note2) actual_note = next(iter(result)) print('test_is_equal; note = {0}'.format(actual_note)) assert actual_note.diatonic_pitch == DiatonicPitch.parse("F#:6") assert actual_note.base_duration == Duration(1, 8) parameter_map[note2].note = actual_note assert policy.verify(parameter_map) is True logging.debug('End test_is_equal')
def print_book_map(tag, f): print(tag) domain_tonality = f.domain_tonality range_tonality = f.range_tonality print('CrossTonalityShiftPitchFunction {0}--> {1}'.format( domain_tonality, range_tonality)) domain_annotation = domain_tonality.annotation[:-1] presentation_reg = 4 domain_presentation_pitches = list() last_pitch = None for t in domain_annotation: domain_pitch = DiatonicPitch(presentation_reg, t) # augment register if crossing past C, e.g. B:4 > C:4 if last_pitch is not None and last_pitch.chromatic_distance > domain_pitch.chromatic_distance: presentation_reg = presentation_reg + 1 domain_pitch = DiatonicPitch(presentation_reg, t) for a in [-1, 0, 1]: a_tone = DiatonicTone.alter_tone_by_augmentation(t, a) domain_pitch_mod = DiatonicPitch(presentation_reg, a_tone) domain_presentation_pitches.append(domain_pitch_mod) last_pitch = domain_pitch for domain_pitch in domain_presentation_pitches: range_pitch = f[domain_pitch] print('{0} --> {1}'.format(domain_pitch, range_pitch))
def __init__(self, name, key, low, high, transpose_up, transpose_interval, parent=None): """ Constructor Args: name: (String) key: (String) key of the instrument low: (String) low written pitch high: (String) high written pitch transpose_up: (boolean) transpose up if true transpose_interval: (interval) transpose interval to the diatonic foundation. parent: (InstrumentBase) parent node in tree. """ InstrumentBase.__init__(self, name, parent) self.__written_low = DiatonicPitch.parse(low) self.__written_high = DiatonicPitch.parse(high) self.__key = key if key else '' self.__transpose_up = transpose_up self.__transpose_interval = transpose_interval # Compute the sounding range for this instrument. if self.transpose_interval: self.__sounding_low = self.transpose_interval.get_end_pitch(self.written_low) if self.transpose_up else \ self.transpose_interval.get_start_pitch(self.written_low) self.__sounding_high = self.transpose_interval.get_end_pitch(self.written_high) if self.transpose_up else \ self.transpose_interval.get_start_pitch(self.written_high) else: self.__sounding_low = self.written_low self.__sounding_high = self.written_high
def test_book_example(self): # Creating a beam with 1/8, 3/8, and 1/16 notes note0 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'd'), Duration(1, 8), 1) note2 = Note(DiatonicPitch(4, 'e'), Duration(1, 16)) beam = Beam([note0, note1, note2]) print(beam)
def get_end_pitch(self, pitch): """ Given a pitch and this interval, Assuming pitch is the starting pitch of the interval, compute the end pitch. Args: pitch: DiatonicPitch Returns: DiatonicPitch of end tone """ diatonic_dist = pitch.diatonic_distance() + self.diatonic_distance tone_index = diatonic_dist % 7 end_pitch_string = DiatonicTone.get_diatonic_letter(tone_index) end_pitch_octave = diatonic_dist // 7 chromatic_dist = pitch.chromatic_distance + self.chromatic_distance normal_pitch = DiatonicPitch( end_pitch_octave, DiatonicFoundation.get_tone(end_pitch_string)) alteration = chromatic_dist - normal_pitch.chromatic_distance end_pitch_string += DiatonicTone.augmentation(alteration) return DiatonicPitch.parse(end_pitch_string + ':' + str(end_pitch_octave))
def _map_non_tonality_tone(self, ttone, pure_tonal_map): # Get the closest tone in terms of chromatic distance. closest_tone, closest_distance = self._find_closest_tone(ttone) dd = closest_tone.diatonic_index - ttone.diatonic_index # Look for octave crossing. if dd in {-5, -6] closest pitch is one octave up. if dd in [-5, -6]: # [1, 2] are alright. pitch < closest_pitch dd = (7 + dd) % 7 elif dd in [5, 6]: # [-1, -2] are alright. pitch > closest_pitch dd = dd - 7 closest_tone_target = pure_tonal_map[closest_tone] index = (closest_tone_target.diatonic_index + dd) % 7 tone = DiatonicToneCache.get_tone('CDEFGAB'[index]) # Octave 4 is chosen arbitrarily, and using dd we determine if ttone and closest need different # octave assignments. We do this in order to get accurate chromatic distances below. if dd < 0: octave = 3 if DiatonicPitch.crosses_c(tone, closest_tone_target, True) else 4 elif dd > 0: octave = 5 if DiatonicPitch.crosses_c(tone, closest_tone_target, False) else 4 else: octave = 4 target_pitch = DiatonicPitch(octave, tone) actual_distance = target_pitch.chromatic_distance - DiatonicPitch(4, closest_tone_target).chromatic_distance # recall: closest_distance is chrom. dist to get from closest pitch to pitch: we are on 'other side', so # we use the negative of it. correction = closest_distance - actual_distance if correction == 0: return tone result_tone = DiatonicTone.alter_tone_by_augmentation(tone, correction) return result_tone
def test_from_book(self): # Quarter note at C:4 note = Note(DiatonicPitch(4, 'c'), Duration(1, 4)) print('{0} duration={1}'.format(note.diatonic_pitch, note.duration)) # Double dotted quarter not at F#:5 note = Note(DiatonicPitch(5, 'f#'), 'Q', 2) print('{0} duration={1}'.format(note.diatonic_pitch, note.duration))
def test_book_example(self): score = Score() # set up 3 instrument voices: 2 violins, 1 trumpet, 1 clarinet catalogue = InstrumentCatalog.instance() score.add_instrument_voice( InstrumentVoice(catalogue.get_instrument("violin"), 2)) score.add_instrument_voice( InstrumentVoice(catalogue.get_instrument("trumpet"))) score.add_instrument_voice( InstrumentVoice(catalogue.get_instrument("clarinet"))) # 1 beat == 1 sec, 3/4 TS + 60 beats per minute, score.tempo_sequence.add(TempoEvent(Tempo(60), Position(0))) score.time_signature_sequence.add( TimeSignatureEvent(TimeSignature(3, Duration(1, 4)), Position(0))) # set up some notes in the two violins violin_voice = score.get_instrument_voice("violin")[0] violin_voice.voice(0).pin( Line([Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'afdecd'])) violin_voice.voice(0).pin( Line([Note(DiatonicPitch(4, y), Duration(1, 4)) for y in 'cdc']))
def _build_non_tonal_pitch_map(self, pmap): octave_start = self._domain_pitch_range.start_index // 12 octave_end = self._domain_pitch_range.end_index // 12 for octave in range(octave_start, octave_end + 1): for ltr in 'ABCDEFG': for aug in ['bb', 'b', '', '#', "##"]: p = DiatonicPitch(octave, DiatonicFoundation.get_tone(ltr + aug)) if self._domain_pitch_range.is_pitch_inbounds(p) and p not in pmap.keys(): closest_p, closest_distance = self._find_closest_pitch(p) if closest_p not in pmap.keys(): continue closest_p_prime = pmap[closest_p] t = self.tonal_function[p.diatonic_tone] if closest_p > p: o = closest_p_prime.octave + 1 if DiatonicPitch.crosses_c(closest_p_prime.diatonic_tone, t, True) else closest_p_prime.octave else: o = closest_p_prime.octave - 1 if DiatonicPitch.crosses_c(closest_p_prime.diatonic_tone, t, False) else closest_p_prime.octave p_prime = DiatonicPitch(o, t) pmap[p] = p_prime # The mapping is not-symmetrical. # e.g. E-pentatonic reflection_tests on G#, f(A#)->G and f(g)->G## return pmap
def test_reversal_on_policy(self): logging.debug('Start test_reversal_on_policy') lower_policy_context = TestRelativeScalarStepConstraint.policy_creator( ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8)) note2 = Note(DiatonicPitch.parse('D:5'), Duration(1, 8)) lower_note_1 = ContextualNote(lower_policy_context) lower_note_2 = ContextualNote( lower_policy_context, Note(DiatonicPitch.parse('C:5'), Duration(1, 8))) p_map = dict([(note1, lower_note_1), (note2, lower_note_2)]) # F#:5 --> G Major two below and 3 above policy = RelativeScalarStepConstraint(note1, note2, -2, 3) result = policy.values(p_map, note1) pitches = [n.diatonic_pitch for n in result] for pitch in pitches: logging.debug(pitch) # Check that each returned verifies for n in result: lower_note_1.note = n assert policy.verify(p_map) logging.debug('End test_reversal_on_policy')
def test_all_g_same_octave_itervals(self): pitches = list('GABCDEF') octaves = [5, 5, 5, 6, 6, 6, 6] augs = ('bb', 'b', '', '#', '##') example_count = 0 exception_items = (1, 2, 5, 10, 15, 16, 20, 21, 25, 30, 31, 35) for i in range(0, 7): pitch = pitches[i] octave = octaves[i] for aug in augs: example_count += 1 a = DiatonicPitch(5, 'G') b = DiatonicPitch(octave, pitch + aug) try: interval = Interval.create_interval(a, b) print('({0}): {1}, {2}) --> {3}'.format(example_count, a, b, interval)) dist = b.diatonic_tone.diatonic_index - a.diatonic_tone.diatonic_index if dist < 0: dist += 7 assert dist == interval.diatonic_distance assert b.chromatic_distance - a.chromatic_distance == interval.chromatic_distance except Exception as e: print('Exception ({0}): ({1}, {2}) : {3}'.format(example_count, a, b, e)) assert example_count in exception_items, \ 'ASSERT ERROR ({0}): ({1}, {2}) : {3}'.format(example_count, a, b, e)
def test_add_note_at_lower_level(self): print('start test_add_note_at_lower_level') sub_beam = Beam([ Note(DiatonicPitch(2, 'c'), Duration(1, 8)), Note(DiatonicPitch(2, 'd'), Duration(1, 8)) ]) beam = Beam([ Note(DiatonicPitch(3, 'c'), Duration(1, 8)), sub_beam, Note(DiatonicPitch(3, 'd'), Duration(1, 8)) ]) AbstractNote.print_structure(beam) notes = beam.get_all_notes() assert len(notes) == 4 assert beam.sub_notes[1].duration == Duration(1, 8) assert beam.sub_notes[1].relative_position == Offset(1, 8) assert beam.sub_notes[1].sub_notes[1].duration == Duration(1, 16) assert beam.sub_notes[1].sub_notes[1].relative_position == Offset( 1, 16) sub_beam.add(Note(DiatonicPitch(2, 'c'), Duration(1, 8)), 1) AbstractNote.print_structure(beam) assert beam.sub_notes[1].duration == Duration(3, 16) assert beam.sub_notes[1].relative_position == Offset(1, 8) assert beam.sub_notes[1].sub_notes[1].duration == Duration(1, 16) assert beam.sub_notes[1].sub_notes[1].relative_position == Offset( 1, 16)
def test_non_scale_note(self): logging.debug('Start test_non_scale_note') note = Note(DiatonicPitch.parse("Bb:4"), Duration(1, 4)) policy = FixedPitchConstraint(note, DiatonicPitch.parse("Ab:5")) policy_context = TestFixedPitchConstraint.policy_creator( ModalityType.Major, DiatonicTone('C'), 'tIV', 'C:2', 'C:8') contextual_note = ContextualNote(policy_context) p_map = PMap() p_map[note] = contextual_note v_result = policy.values(p_map, note) result = next(iter(v_result)) print('test_non_scale_note note= {0}'.format(result)) assert result.diatonic_pitch == DiatonicPitch.parse("Ab:5") assert result.base_duration == Duration(1, 4) contextual_note.note = result result = policy.verify(p_map) assert result is True logging.debug('end test_non_scale_note')
def __create_chord_on_diatonic_tonality(self, diatonic_tone, diatonic_tonality): if not diatonic_tonality: raise Exception( "Cannot base secundal chord on tone {0} without tonality.". format(diatonic_tone.diatonic_symbol)) # The tonality must include this tone. tone_scale = diatonic_tonality.annotation found_index = -1 for i in range(0, len(tone_scale)): if diatonic_tone == tone_scale[i]: found_index = i break if found_index == -1: raise Exception( "For secundal chord based on tone {0}, tone must be in given tonality {1}" .format(diatonic_tone.diatonic_symbol, diatonic_tonality)) self.chord_basis = [] basis_tone = tone_scale[found_index] for i in range(0, 3): tone = tone_scale[(found_index + i) % (len(tone_scale) - 1)] pitch_a = DiatonicPitch(1, basis_tone.diatonic_symbol) b_octave = 2 if basis_tone.diatonic_index > tone.diatonic_index else 1 pitch_b = DiatonicPitch(b_octave, tone.diatonic_symbol) interval = Interval.create_interval(pitch_a, pitch_b) # If for any reason, the interval is not perfect or augmented (we know it is a 4th), just adjust tone upward # It is unknown if this can happen in a diatonic scale in practice. if interval.interval_type.value == IntervalType.Diminished: tone = DiatonicTone.alter_tone_by_augmentation(tone, 1) pitch_b = DiatonicPitch(b_octave, tone.diatonic_symbol) interval = Interval.create_interval(pitch_a, pitch_b) self.chord_basis.append(interval) self.__tones.append((tone, interval)) basis_tone = tone
def test_is_not_equal(self): logging.debug('Start test_is_not_equal') note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8)) lower_policy_context = TestNotEqualPitchConstraint.policy_creator( ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') lower_context_note_a = ContextualNote( lower_policy_context, Note(DiatonicPitch.parse('F#:6'), Duration(1, 8))) p_map = PMap() p_map[note1] = lower_context_note_a other_source = [] for tone in ['B:5', 'D:5', 'E:5']: n = Note(DiatonicPitch.parse(tone), Duration(1, 8)) lower_context_note = ContextualNote(lower_policy_context) p_map[n] = lower_context_note other_source.append(n) params = list([note1]) params.extend(other_source) policy = NotEqualPitchConstraint(params) for c_note in p_map.unassigned_actors(policy): print(c_note) v_result = policy.values(p_map, c_note) assert v_result is not None assert DiatonicPitch.parse('F#:6') not in { n.diatonic_pitch for n in v_result } p_map[other_source[1]].note = Note(DiatonicPitch.parse('E:6'), Duration(1, 8)) for c_note in p_map.unassigned_actors(policy): print(c_note) v_result = policy.values(p_map, c_note) assert v_result is not None ret_pitches = {n.diatonic_pitch for n in v_result} assert len( ret_pitches.intersection( {DiatonicPitch.parse('F#:6'), DiatonicPitch.parse('E:6')})) == 0 assert policy.verify(p_map) is False p_map[other_source[2]].note = Note(DiatonicPitch.parse('F#:6'), Duration(1, 8)) assert policy.verify(p_map) is False p_map[other_source[0]].note = Note(DiatonicPitch.parse('D:6'), Duration(1, 8)) assert policy.verify(p_map) is False p_map[other_source[2]].note = Note(DiatonicPitch.parse('A:6'), Duration(1, 8)) assert policy.verify(p_map) is True logging.debug('End test_is_not_equal') return
def test_major_modality(self): print('Testing Major Modality: D-Major, cue=G:4') domain_tonality = Tonality.create(ModalityType.Major, DiatonicFoundation.get_tone('D')) cue_pitch = DiatonicPitch.parse('G:4') domain_pitch_range = PitchRange.create('D:3', 'C#:6') f = ChromaticPitchReflectionFunction(domain_tonality, cue_pitch, domain_pitch_range, FlipType.CenterTone) TestChromaticPitchReflectionFunction.print_function(f) # Ensure all domain keys are in the domain_pitch_range for pitch in f.domain: assert domain_pitch_range.is_pitch_inbounds(pitch), \ 'Pitch {0} is not in range {1}.'.format(pitch, domain_pitch_range) assert DiatonicPitch.parse('D:3') in f.domain assert DiatonicPitch.parse('C#:6') in f.domain # Test for octave coverage assert 6 == f['D:3'].octave assert 5 == f['C#:4'].octave assert 5 == f['D:4'].octave assert 4 == f['C#:5'].octave assert 4 == f['D:5'].octave assert 3 == f['C#:6'].octave
def simple_reflection_example(): print('-------------- Simple reflection --------------------------') source_expression = '{<C-Major: I> iC:4 C qD E <:IV> iF G hA <:V> ig b qf g <:VI> ie e qd ic d <:I> h@c}' t_flip = TDiatonicReflection.create(source_expression, DiatonicPitch.parse('F:4')) print('Flip examples based on:') print_line(t_flip.source_line) print_hct(t_flip.source_hct) print() print('Flip on F:4 (Figure 16.9)') target_line, target_hct = t_flip.apply() print_line(target_line) print_hct(target_hct) print() t_reflect = TDiatonicReflection.create(source_expression, DiatonicPitch.parse('A:4')) target_line, target_hct = t_reflect.apply() print('Flip on A:4 (Figure 16.10)') print_line(target_line) print_hct(target_hct) print()
def test_book_examples(self): # Interval Creation interval = Interval(5, IntervalType.Perfect) print(interval) interval = Interval.parse("m:10") print(interval) interval = Interval.create_interval(DiatonicPitch.parse("a:3"), DiatonicPitch.parse("f#:4")) print(interval) # Interval Addition/Subtraction i1 = Interval(5, IntervalType.Perfect) i2 = Interval.parse("M:3") interval = i1 + i2 print(interval) interval = i1 - i2 print(interval) interval += i2 print(interval) interval -= i2 print(interval) # compute end and start interval = Interval(5, IntervalType.Perfect) pitch = interval.get_end_pitch(DiatonicPitch.parse("F#:5")) print(pitch) pitch = interval.get_start_pitch(DiatonicPitch.parse("C:5")) print(pitch)
def test_basic_construction(self): note = Note(DiatonicPitch(4, 'c'), Duration(1, 4)) print(note) assert note.base_duration == Duration(1, 4) assert note.duration == Duration(1, 4) assert str(note.diatonic_pitch) == 'C:4' assert not note.is_rest # quarter rest note = Note(None, Duration(1, 4)) print(note) assert note.base_duration == Duration(1, 4) assert note.duration == Duration(1, 4) assert note.diatonic_pitch is None assert note.is_rest note = Note(DiatonicPitch(4, 'c'), Duration(1, 4), 2) print(note) assert note.base_duration == Duration(1, 4) assert note.duration == Duration(7, 16) assert str(note.diatonic_pitch) == 'C:4' assert not note.is_rest note = Note(DiatonicPitch(5, 'f#'), 'Q', 2) print(note) assert note.base_duration == Duration(1, 4) assert note.duration == Duration(7, 16) assert str(note.diatonic_pitch) == 'F#:5' assert not note.is_rest
def calculate_interval(tone_1, tone_2, near_interval): """ The purpose of this method is to find a transform interval close to 'near_interval'. This is used to determine the transform interval for secondary chords, wherein the obvious jump does not match transform interval (e.g. major to minor scale), and as well must be adjusted for the number and sign of octaves nearest interval may have. See test cases: test_modal_secondary_tonality where best_interval == d:4 and near_interval == P:4 E-MM to Ab-MM using V/III chord. :param tone_1: :param tone_2: :param near_interval: :return: """ sign = TShift._sign(near_interval.chromatic_distance) start, increment = (1, 1) if sign == 1 else (7, -1) p1 = DiatonicPitch(start, tone_1) oct_2 = start best = 100000 best_interval = None while abs(oct_2) < 7: p2 = DiatonicPitch(oct_2, tone_2) i = TonalInterval.create_interval(p1, p2) if TShift._sign(i.chromatic_distance) != sign: oct_2 = oct_2 + sign continue diff = abs(near_interval.chromatic_distance - i.chromatic_distance) if diff < best: best = diff best_interval = i else: break oct_2 = oct_2 + sign return best_interval
def __create_chord_on_diatonic_tonality(self, diatonic_tone, diatonic_tonality): if not diatonic_tonality: raise Exception( "Cannot base quartal chord on tone {0} without tonality.". format(diatonic_tone.diatonic_symbol)) # The tonality must include this tone. tone_scale = diatonic_tonality.annotation found_index = -1 for i in range(0, len(tone_scale)): if diatonic_tone == tone_scale[i]: found_index = i break if found_index == -1: raise Exception( "For quartal chord based on tone {0}, tone must be in given tonality {1}" .format(diatonic_tone.diatonic_symbol, diatonic_tonality)) self.chord_basis = [] basis_tone = tone_scale[found_index] for i in range(0, 3): tone = tone_scale[(found_index + 3 * i) % (len(tone_scale) - 1)] pitch_a = DiatonicPitch(1, basis_tone.diatonic_symbol) b_octave = 2 if basis_tone.diatonic_index > tone.diatonic_index else 1 pitch_b = DiatonicPitch(b_octave, tone.diatonic_symbol) interval = Interval.create_interval(pitch_a, pitch_b) self.chord_basis.append(interval) self.__tones.append((tone, interval)) basis_tone = tone
def test_simple_major_scale_descent_two_steps(self): logging.debug('Start test_simple_major_scale_descent_two_steps') upper_context_notes = list() for s in ['C:6', 'A:5', 'F:5', 'D:5', 'B:4']: upper_context_notes.append(Note(DiatonicPitch.parse(s), Duration(1, 8))) lower_policy_context = TestPitchStepConstraint.policy_creator(ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') lower_context_notes = list() for s in range(0, len(upper_context_notes)): lower_context_notes.append(ContextualNote(lower_policy_context)) lower_context_notes[0].note = Note(DiatonicPitch.parse("E:5"), Duration(1, 8)) parameter_map = dict() policies = [] for s, sp in zip(upper_context_notes, lower_context_notes): parameter_map[s] = sp for i in range(0, len(upper_context_notes) - 1): policies.append(PitchStepConstraint(upper_context_notes[i], upper_context_notes[i + 1], 2, PitchStepConstraint.Down)) answers = ['C:5', 'A:4', 'F#:4', 'D:4'] for policy, answer in zip(policies, answers): result = policy.values(parameter_map, policy.note_two) note = next(iter(result)) print(note) assert str(note.diatonic_pitch) == answer parameter_map[policy.note_two].note = note assert policy.verify(parameter_map) logging.debug('End test_simple_major_scale_descent_two_steps')
def test_basic_policy(self): logging.debug('Start test_basic_policy') lower_policy_context = TestRelativeScalarStepConstraint.policy_creator( ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') note1 = Note(DiatonicPitch.parse('C:5'), Duration(1, 8)) note2 = Note(DiatonicPitch.parse('D:5'), Duration(1, 8)) lower_note_1 = ContextualNote( lower_policy_context, Note(DiatonicPitch.parse('F#:5'), Duration(1, 8))) lower_note_2 = ContextualNote(lower_policy_context) p_map = dict([(note1, lower_note_1), (note2, lower_note_2)]) # F#:5 --> G Major two below and 3 above policy = RelativeScalarStepConstraint(note1, note2, -2, 3) v_result = policy.values(p_map, note2) pitches = [n.diatonic_pitch for n in v_result] assert len(pitches) == 6 for s in ['D:5', 'E:5', 'F#:5', 'G:5', 'A:5', 'B:5']: assert DiatonicPitch.parse(s) in pitches for note in v_result: logging.debug(note) # Check verify for each answer for n in v_result: lower_note_2.note = n assert policy.verify(p_map) logging.debug('End test_basic_policy')
def test_adding_notes(self): score = Score() # set up 3 instrument voices: 2 violins, 1 trumpet, 1 clarinet catalogue = InstrumentCatalog.instance() score.add_instrument_voice( InstrumentVoice(catalogue.get_instrument("violin"), 2)) # 1 beat == 1 sec, 3/4 TS + 60 beats per minute, score.tempo_sequence.add(TempoEvent(Tempo(60), Position(0))) score.time_signature_sequence.add( TimeSignatureEvent(TimeSignature(3, Duration(1, 4)), Position(0))) violin_voice = score.get_instrument_voice("violin")[0] line = Line([Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'afd']) violin_voice.voice(0).pin(line) notes = violin_voice.get_all_notes() for n in notes: print(n) line.append(Note(DiatonicPitch(4, 'g'), Duration(1, 8))) notes = violin_voice.get_all_notes() for n in notes: print(n)
def test_for_book_example_2(self): print('----- test for book example 2 -----') source_instance_expression = '{<A-Major:i> [sA:4 A A A] qA:4 [iA:4 A] <:iv> qA:4 [sA:4 A A A] qA:4}' target_instance_expression = '{<G-Major:i> wA:4 <:iv> wA:4}' lge = LineGrammarExecutor() source_instance_line, source_instance_hct = lge.parse( source_instance_expression) actors = source_instance_line.get_all_notes() for a in actors: print("{0}".format(a)) target_instance_line, target_instance_hct = lge.parse( target_instance_expression) target_hcs = target_instance_hct.hc_list() for hc in target_hcs: print("{0}".format(hc)) pitch_range = PitchRange( DiatonicPitch.parse('C:4').chromatic_distance, DiatonicPitch.parse('C:6').chromatic_distance) p_map = PMap.create(source_instance_expression, pitch_range, [('G-Major:I', Duration(3, 4)), ('G-Major:IV', Duration(3, 4))]) actors = p_map.actors policies = OrderedSet() policies.add( StepSequenceConstraint( [actors[0], actors[1], actors[2], actors[3]], [1, 1, 1])) policies.add(ChordalPitchConstraint(actors[0])) policies.add(ChordalPitchConstraint(actors[4])) policies.add(ChordalPitchConstraint(actors[8])) policies.add( StepSequenceConstraint( [actors[8], actors[9], actors[10], actors[11]], [1, -1, -1])) policies.add(EqualPitchConstraint([actors[0], actors[12]])) policies.add(EqualPitchConstraint([actors[4], actors[7]])) policies.add( RelativeDiatonicConstraint(actors[4], actors[5], Interval(3, IntervalType.Major), Interval(1, IntervalType.Perfect))) policies.add(StepSequenceConstraint([actors[5], actors[6]], [-1])) # policies.add(ChordalPitchConstraint(actors[7])) solver = PitchConstraintSolver(policies) full_results, partial_results = solver.solve(p_map) print('Results has {0} results.'.format(len(full_results))) for pm in full_results: if str(pm[actors[7]].note.diatonic_pitch) == 'D:4' and str( pm[actors[0]].note.diatonic_pitch) == 'G:4': print("{0}".format(pm))
def test_pentatonic_tonal_function(self): t_domain = Tonality.create(ModalityType.MinorPentatonic, DiatonicTone('C')) i = Interval(5, IntervalType.Perfect) r = PitchRange.create('E:3', 'E:7') f = CrossTonalityShiftPitchFunction(t_domain, r, i) print('f={0}'.format(f)) TestCrossTonalityShiftPitchFunction.print_map( 'test_pentatonic_tonal_function', f) t = f.tonal_function print(t) assert 'G' == t['C'].diatonic_symbol assert 'Bb' == t['Eb'].diatonic_symbol assert 'C' == t['F'].diatonic_symbol assert 'D' == t['G'].diatonic_symbol assert 'F' == t['Bb'].diatonic_symbol assert 'G:5' == str(f['C:5']) assert 'F:5' == str(f['Bb:4']) assert 'D:5' == str(f['G:4']) assert 'C:5' == str(f['F:4']) assert 'Bb:4' == str(f['Eb:4']) assert 'G:4' == str(f['C:4']) # test range d = f.domain_pitch_range print(d) assert d.start_index == DiatonicPitch.parse('E:3').chromatic_distance assert d.end_index == DiatonicPitch.parse('E:7').chromatic_distance r = f.range_pitch_range print(r) assert r.start_index == DiatonicPitch.parse('B:3').chromatic_distance assert r.end_index == DiatonicPitch.parse('B:7').chromatic_distance # test chromatics assert 'G#:5' == str(f['C#:5']) assert 'F#:5' == str(f['B:4']) assert 'E#:5' == str(f['A#:4']) assert 'E:5' == str(f['A:4']) assert 'D#:5' == str(f['G#:4']) assert 'C#:5' == str(f['F#:4']) assert 'B:4' == str(f['E:4']) assert 'A:4' == str(f['D:4']) assert 'A#:4' == str(f['D#:4']) assert 'G#:4' == str(f['C#:4']) assert 'Gb:5' == str(f['Cb:5']) assert 'Fb:5' == str(f['Bbb:4']) assert 'Eb:5' == str(f['Ab:4']) assert 'Db:5' == str(f['Gb:4']) assert 'Cb:5' == str(f['Fb:4']) assert 'Bbb:4' == str(f['Ebb:4']) assert 'Ab:4' == str(f['Db:4']) assert 'Gb:4' == str(f['Cb:4'])