def test_major_modal_key(self): tonality = Tonality.create(ModalityType.Major, 'D', 1) assert ModalityType.Major == tonality.modality_type assert ModalityType.Major == tonality.modality.modality_type assert 1 == tonality.modal_index assert 'D' == tonality.diatonic_tone.diatonic_symbol assert 'C' == tonality.basis_tone.diatonic_symbol assert ['D', 'E', 'F', 'G', 'A', 'B', 'C', 'D'] == [t.diatonic_symbol for t in tonality.annotation]
def policy_creator(modality_type, modality_tone, tertian_chord_txt, low_pitch_txt, hi_pitch_txt): diatonic_tonality = Tonality.create(modality_type, modality_tone) chord = TertianChordTemplate.parse(tertian_chord_txt).create_chord( diatonic_tonality) hc = HarmonicContext(diatonic_tonality, chord, Duration(1, 2)) pitch_range = PitchRange( DiatonicPitch.parse(low_pitch_txt).chromatic_distance, DiatonicPitch.parse(hi_pitch_txt).chromatic_distance) return PolicyContext(hc, pitch_range)
def test_low_range(self): ranges = PitchRange.create("A:0", "C:5") for modality_type in SYSTEM_MODALITIES: for validTone in ModalityFactory.create_modality(modality_type).get_valid_root_tones(): tonality = Tonality.create(modality_type, DiatonicFoundation.get_tone(validTone)) pitch_scale = PitchScale(tonality, ranges) print('Scale {0} {1} on {2}: {3}'.format(validTone, modality_type.name, ranges, ','.join(map(get_symbol, pitch_scale.pitch_scale)))) scale_check(pitch_scale, tonality)
def test_interesting(self): diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("F")) template = SecondaryChordTemplate.parse('V/V[NaturalMinor]') print(template) t_chord = template.create_chord(diatonic_tonality) print(t_chord) s = ', '.join(str(tone[0].diatonic_symbol) for tone in t_chord.tones) print(s) assert s == 'G, Bb, D'
def test_simple_tonal_permutation(self): t_domain = Tonality.create(ModalityType.Major, DiatonicTone('E')) cycles = [['E', 'G#', 'A', 'B'], ('F#', 'G#')] p = TonalityPermutation(t_domain, cycles) assert DiatonicToneCache.get_tone('G#') == p['E'] assert DiatonicToneCache.get_tone('A') == p['F#'] assert DiatonicToneCache.get_tone('F#') == p['G#'] assert DiatonicToneCache.get_tone('B') == p['A'] assert DiatonicToneCache.get_tone('E') == p['B'] assert DiatonicToneCache.get_tone('C#') == p['C#'] assert DiatonicToneCache.get_tone('D#') == p['D#']
def construct_tonality(self, tone, modality_str, modal_index=0): if modality_str[0] == '!': modality_type = ModalityType(modality_str[1:]) elif modality_str in LineConstructor.MODALITY_SHORT_NAME_MAP: modality_type = LineConstructor.MODALITY_SHORT_NAME_MAP[modality_str] else: modality_type = ModalityType(modality_str) if ModalityFactory.is_registered(modality_type): return Tonality.create_on_basis_tone(tone, modality_type, modal_index) else: raise Exception('Modality \'{0}\' is not registered in ModalityFactory.'.format(modality_str))
def test_simple_tertian(self): diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C")) chord_list = ChordClassifier.classify(['e', 'a', 'c', 'g', 'B'], 'a', diatonic_tonality) assert 2 == len(chord_list) TestChordClassifier.print_chord_list('test_simple_tertian', chord_list) chord_list = ChordClassifier.classify(['e', 'a', 'c', 'g', 'B'], 'a') TestChordClassifier.print_chord_list('test_simple_tertian', chord_list) assert 2 == len(chord_list)
def test_basic_setup(self): c = InstrumentCatalog.instance() violin = c.get_instrument("violin") # Add notes to the score vnote0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) vnote1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) vnote2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) vnote3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) vnote4 = Note(DiatonicPitch(4, 'e'), Duration(1, 8)) vnote5 = Note(DiatonicPitch(4, 'f'), Duration(1, 8)) # Set up a violin voice with 6 8th notes vline = Line([vnote0, vnote1, vnote2, vnote3, vnote4, vnote5]) tempo_seq = TempoEventSequence() ts_seq = EventSequence() tempo_seq.add(TempoEvent(Tempo(60), Position(0))) ts_seq.add( TimeSignatureEvent(TimeSignature(3, Duration(1, 4), 'sww'), Position(0))) hc_track = HarmonicContextTrack() diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C")) chord_t = TertianChordTemplate.parse('tIV') chord = chord_t.create_chord(diatonic_tonality) hc_track.append(HarmonicContext(diatonic_tonality, chord, Duration(2))) score = LiteScore(vline, hc_track, violin, tempo_seq, ts_seq) bp = score.beat_position(Position(0)) print(bp) assert bp.beat_number == 0 bp = score.beat_position(Position(5, 8)) print(bp) assert bp.measure_number == 0 assert bp.beat_number == Fraction(5, 2) assert int(bp.beat_number) == 2 assert bp.beat_number - bp.beat == Fraction(1, 2) tse = score.time_signature_sequence.floor_event(Position(5, 8)) assert tse is not None print(tse.object.beat_type(bp.beat)) assert tse.object.beat_type(bp.beat) == BeatType.Weak assert bp.beat_fraction == Fraction(1, 2) bp = score.beat_position(Position(1, 16)) print(bp) tse = score.time_signature_sequence.floor_event(Position(1, 16)) print(tse.object.beat_type(bp.beat)) assert tse.object.beat_type(bp.beat) == BeatType.Strong
def test_simple_secundal(self): diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C")) chord_list = ChordClassifier.classify(['d', 'c', 'e'], 'c', diatonic_tonality) assert 1 == len(chord_list) assert "MajMaj" == str(chord_list[0].chord_type) TestChordClassifier.print_chord_list('test_simple_secundal', chord_list) chord_list = ChordClassifier.classify(['d', 'c', 'e', 'f'], 'c', diatonic_tonality) TestChordClassifier.print_chord_list('test_simple_secundal', chord_list) assert 0 == len(chord_list)
def test_simple_id(self): t_domain = Tonality.create(ModalityType.Major, DiatonicTone('E')) p = TonalityPermutation(t_domain) print(p) assert DiatonicToneCache.get_tone('E') == p['E'] assert DiatonicToneCache.get_tone('F#') == p['F#'] assert DiatonicToneCache.get_tone('G#') == p['G#'] assert DiatonicToneCache.get_tone('A') == p['A'] assert DiatonicToneCache.get_tone('B') == p['B'] assert DiatonicToneCache.get_tone('C#') == p['C#'] assert DiatonicToneCache.get_tone('D#') == p['D#']
def test_book_example(self): print("------- test_book_example") # Test for scalar range map tonality = Tonality.create(ModalityType.Major, 'C', 0) # 11 scalar notes to C:4 to G:5 interpreter = ScalarRangeInterpreter(tonality, DiatonicPitch.parse('C:4'), 0, Fraction(5, 2)) for i in range(0, 12): p = interpreter.eval_as_nearest_pitch(Fraction(5 * i, 2)) print('[{0}] {1}'.format(i, p))
def test_adapted_function(self): t_domain = Tonality.create(ModalityType.Major, DiatonicTone('F')) t_range = Tonality.create(ModalityType.MelodicMinor, DiatonicTone('G')) pmap = { 'F': 'G', 'G': 'F#', 'A': 'E', 'Bb': 'A', 'C': 'D', 'D': 'Bb', 'E': 'C' } f = TonalFunction(t_domain, t_range, pmap) nt_domain = Tonality.create(ModalityType.Major, DiatonicTone('Ab')) nt_range = Tonality.create(ModalityType.MelodicMinor, DiatonicTone('e')) pf = f.create_adapted_function(nt_domain, nt_range) assert 'E' == str(pf['Ab'].diatonic_symbol) assert 'D#' == str(pf['Bb'].diatonic_symbol) assert 'C#' == str(pf['C'].diatonic_symbol) assert 'F#' == str(pf['Db'].diatonic_symbol) assert 'B' == str(pf['Eb'].diatonic_symbol) assert 'G' == str(pf['F'].diatonic_symbol) assert 'A' == str(pf['G'].diatonic_symbol) # Test chromatics f['G#'] = 'F##' f['Gb'] = 'F' f['B'] = 'Db' # aug 4th --> dim 5th pf = f.create_adapted_function(nt_domain, nt_range) assert 'D##' == str(pf['B'].diatonic_symbol) assert 'Bb' == str(pf['D'].diatonic_symbol ) # D is aug 4th in Ab; Bb is dim 5th in e minor
def test_extension_map(self): t_domain = Tonality.create(ModalityType.Major, DiatonicTone('C')) t_range = Tonality.create(ModalityType.Major, DiatonicTone('A')) extension_map = {'C#': 'A#', 'D#': 'C', 'Gb': 'G#'} # default map between 2 tonalities of same cardinality. f = TonalFunction(t_domain, t_range, None, extension_map) assert DiatonicToneCache.get_tone('A') == f['C'] assert DiatonicToneCache.get_tone('B') == f['D'] assert DiatonicToneCache.get_tone('C#') == f['E'] assert DiatonicToneCache.get_tone('D') == f['F'] assert DiatonicToneCache.get_tone('E') == f['G'] assert DiatonicToneCache.get_tone('F#') == f['A'] assert DiatonicToneCache.get_tone('G#') == f['B'] assert f['Db'] is None assert DiatonicToneCache.get_tone('A#') == f['C#'] assert DiatonicToneCache.get_tone('C') == f['D#'] assert f['Eb'] is None assert DiatonicToneCache.get_tone('G#') == f['Gb'] assert f['F#'] is None
def test_pentatonic_tonal_function_book(self): t_domain = Tonality.create(ModalityType.MajorPentatonic, DiatonicTone('C')) f = CrossTonalityShiftTonalFunction(t_domain, "G#", 2) # C, D, E, G. A ==> G#, B, C#, E, F# assert 'G#' == f['C'].diatonic_symbol assert 'B' == f['D'].diatonic_symbol assert 'C#' == f['E'].diatonic_symbol assert 'E' == f['G'].diatonic_symbol assert 'F#' == f['A'].diatonic_symbol assert 'G' == f['B'].diatonic_symbol assert 'D' == f['F'].diatonic_symbol
def create_score(s_notes, modality, key_tone, chords, instrument, ts): diatonic_tonality = Tonality.create(modality, DiatonicToneCache.get_tone(key_tone)) hc_track = TestTReshape.create_track(chords, diatonic_tonality) tempo_seq = TempoEventSequence() ts_seq = EventSequence() tempo_seq.add(TempoEvent(Tempo(60, Duration(1, 4)), Position(0))) ts_seq.add(TimeSignatureEvent(TimeSignature(ts[0], Duration(1, ts[1]), ts[2]), Position(0))) c = InstrumentCatalog.instance() violin = c.get_instrument(instrument) return LiteScore(TestTReshape.create_line(s_notes), hc_track, violin, tempo_seq, ts_seq)
def test_pa_4_chords(self): print('test_pa_4_chords') chord_types = ['PPP', 'PPA', 'PAP', 'PAA', 'APP', 'APA', 'AAP', 'AAA'] answers = ['C, F, Bb, Eb PPP', 'C, F, Bb, E PPA', 'C, F, B, E PAP', 'C, F, B, E# PAA', 'C, F#, B, E APP', 'C, F#, B, E# APA', 'C, F#, B#, E# AAP', 'C, F#, B#, E## AAA'] tonality = Tonality.create(ModalityType.Major, DiatonicTone("C")) for triad, a in zip(chord_types, answers): chord_t = QuartalChordTemplate.parse('qC' + triad) print(chord_t) chord = chord_t.create_chord(tonality) tones = chord.tones s = '{0} {1}'.format(', '.join(tone[0].diatonic_symbol for tone in tones), chord.chord_type) print(s) assert s == a, '{0} != {1}'.format(s, a)
def test_build_user_defined_tonality(self): modality_type = ModalityType('my_modality') incremental_interval_strs = [ 'P:1', 'm:2', 'M:3', 'm:2', 'm:2', 'M:2', 'A:2' ] modality_spec = ModalitySpec(modality_type, incremental_interval_strs) modality = Modality(modality_spec) tonality = Tonality(modality, 'A') assert 0 == tonality.modal_index assert 'A' == tonality.diatonic_tone.diatonic_symbol assert ['A', 'Bb', 'D', 'Eb', 'Fb', 'Gb', 'A'] == [t.diatonic_symbol for t in tonality.annotation]
def test_shift_create(self): t_domain = Tonality.create(ModalityType.MelodicMinor, DiatonicTone('C')) i = Interval(5, IntervalType.Perfect) r = PitchRange.create('E:3', 'E:7') f = CrossTonalityShiftPitchFunction(t_domain, r, i) assert 'P:5' == str(f.root_shift_interval) assert 'G:4' == str(f['C:4']) assert 'A:4' == str(f['D:4']) assert 'B:4' == str(f['E:4']) assert 'C:5' == str(f['F:4'])
def create_score_artifacts(modality, key_tone, chords, ts): diatonic_tonality = Tonality.create( modality, DiatonicToneCache.get_tone(key_tone)) hc_track = TestPitchFitFunction.create_track(chords, diatonic_tonality) tempo_seq = TempoEventSequence() ts_seq = EventSequence() tempo_seq.add(TempoEvent(Tempo(60, Duration(1, 4)), Position(0))) ts_seq.add( TimeSignatureEvent(TimeSignature(ts[0], Duration(1, ts[1]), ts[2]), Position(0))) return hc_track, tempo_seq, ts_seq
def test_reversal_tonal_function(self): t_domain = Tonality.create(ModalityType.Major, DiatonicTone('G')) cycles = [['C'], ['B', 'D'], ['E', 'A'], ['G', 'F#']] permutation_function = TonalityPermutationFunction.create( t_domain, cycles) r = PitchRange.create('E:3', 'E:7') f = TonalityPitchFunction(permutation_function, ('E:4', 'E:4'), r, True) TestTonalityPitchFunction.print_map('test_reversal_tonal_function', f) assert 'C:5' == str(f['C:5'])
def test_defined_map(self): t_domain = Tonality.create(ModalityType.Major, DiatonicTone('C')) t_range = Tonality.create(ModalityType.MelodicMinor, DiatonicTone('A')) pmap = { 'C': 'A', 'D': 'B', 'E': 'C', 'F': 'D', 'G': 'E', 'A': 'F#', 'B': 'G#' } # default map between 2 tonalities of same cardinality. f = TonalFunction(t_domain, t_range, pmap) assert DiatonicToneCache.get_tone('A') == f['C'] assert DiatonicToneCache.get_tone('B') == f['D'] assert DiatonicToneCache.get_tone('C') == f['E'] assert DiatonicToneCache.get_tone('D') == f['F'] assert DiatonicToneCache.get_tone('E') == f['G'] assert DiatonicToneCache.get_tone('F#') == f['A'] assert DiatonicToneCache.get_tone('G#') == f['B']
def test_melodic_minor_modality(self): print('Testing Melodic Minor Modality: C-MelodicMinor, cue=Eb:3') domain_tonality = Tonality.create(ModalityType.MelodicMinor, DiatonicFoundation.get_tone('C')) cue_pitch = DiatonicPitch.parse('Eb:3') domain_pitch_range = PitchRange.create('D:4', 'F:5') f = ChromaticPitchReflectionFunction(domain_tonality, cue_pitch, domain_pitch_range, FlipType.CenterTone) TestChromaticPitchReflectionFunction.print_function(f) assert 2 == f['D:4'].octave assert 2 == f['G:4'].octave assert 1 == f['A:4'].octave assert 1 == f['C:5'].octave assert 1 == f['f:5'].octave
def test_inversion(self): ctype = 'ADom7' chords = {1: ['A', 'C#', 'E', 'G'], 2: ['C#', 'A', 'E', 'G'], 3: ['E', 'A', 'C#', 'G'], 4: ['G', 'A', 'C#', 'E']} diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C")) for i in range(1, 5): template = TertianChordTemplate.parse(ctype + '@' + str(i)) chord = template.create_chord(diatonic_tonality) tones = chord.tones print(', '.join(tone[0].diatonic_symbol for tone in tones)) assert TestTertianTemplateChord.verify(tones, chords[i]), \ 'Fail #{0}, {1}'.format(ctype + '@' + str(i), ', '.join(tone[0].diatonic_symbol for tone in tones))
def test_natural_minor_modality(self): print('Testing Natural Minor Modality: C-Major, cue=Eb:3') domain_tonality = Tonality.create(ModalityType.NaturalMinor, DiatonicFoundation.get_tone('C')) cue_pitch = DiatonicPitch.parse('Eb:3') domain_pitch_range = PitchRange.create('D:2', 'F:4') f = ChromaticPitchReflectionFunction(domain_tonality, cue_pitch, domain_pitch_range, FlipType.CenterTone) TestChromaticPitchReflectionFunction.print_function(f) # Test for octave coverage assert 4 == f['D:2'].octave assert 3 == f['Bb:2'].octave assert 3 == f['C:3'].octave assert 2 == f['Bb:3'].octave assert 2 == f['F:4'].octave
def __init__(self, secondary_chord_template, diatonic_tonality, secondary_tonality=None): """ Constructor. :param secondary_chord_template: SecondaryChordTemplate :param diatonic_tonality: DiatonicTonality (used in scale degree chord formation) :param secondary_tonality: Used to represent denominator tonality Note: The means for determining the secondary tonality is not necessarily clean. The standard technique involves inferring the modality from the triad built on the i-th tone of the base modality. However, the actual technique to be used can be a variable. The secondary_tonality argument is meant for cases where the standard technique does not hold up - and provides a means for specifying the exact secondary tonality when the standard technique does not apply. """ Chord.__init__(self, secondary_chord_template, diatonic_tonality) # Build the tonality upon which the primary chord is based diatonic_basis = self.diatonic_tonality.get_tone( self.chord_template.secondary_scale_degree - 1) # if no secondary modality specified? # Use diatonic_tonality + secondary scale degree. Determine the triad type of the natural triad there, and # if major, use major modality. If minor, use melodic minor modality. Otherwise flag an error. if not self.chord_template.secondary_modality: triad = TertianChordTemplate.get_triad( diatonic_tonality, self.chord_template.secondary_scale_degree) if triad: modality = ModalityType.Major if triad.chord_type.value == TertianChordType.Maj or \ triad.chord_type.value == TertianChordType.Aug else \ ModalityType.MelodicMinor if triad.chord_type.value == TertianChordType.Min or \ triad.chord_type.value == TertianChordType.Dim else None if modality is None: raise Exception( 'Illegal secondary modality for secondary chord') else: raise Exception( 'Cannot determine secondary modality for secondary chord') else: modality = self.chord_template.secondary_modality self.__secondary_tonality = Tonality.create(modality, diatonic_basis) \ if not secondary_tonality else secondary_tonality # Create the principal chord self.__primary_chord = self.chord_template.principal_chord_template.create_chord( self.secondary_tonality)
def _build_primary_map(self): domain_scale = self.domain_tonality.annotation[:-1] tonal_map = dict() if self.reflect_type == FlipType.CenterTone: for tone in domain_scale: interval = Interval.calculate_tone_interval(tone, self.cue_tone) end_tone = interval.get_end_tone(self.cue_tone) tonal_map[tone] = end_tone else: if self.reflect_type == FlipType.LowerNeighborOfPair: lower_index = domain_scale.index(self.cue_tone) upper_index = (lower_index + 1) % len(domain_scale) else: upper_index = domain_scale.index(self.cue_tone) lower_index = (upper_index - 1) % len(domain_scale) tonal_map[domain_scale[upper_index]] = domain_scale[lower_index] tonal_map[domain_scale[lower_index]] = domain_scale[upper_index] last_lower = domain_scale[lower_index] last_upper = domain_scale[upper_index] for i in list(reversed(range(0, lower_index))): new_lower = domain_scale[i] interval = Interval.calculate_tone_interval(new_lower, last_lower) new_upper = interval.get_end_tone(last_upper) tonal_map[new_lower] = new_upper last_lower = new_lower last_upper = new_upper last_lower = domain_scale[lower_index] last_upper = domain_scale[upper_index] for i in list(range((upper_index + 1), len(domain_scale))): new_upper = domain_scale[i] interval = Interval.calculate_tone_interval(last_upper, new_upper) new_lower = interval.negation().get_end_tone(last_lower) tonal_map[new_upper] = new_lower last_lower = new_lower last_upper = new_upper range_tones = list(reversed([tonal_map[tone] for tone in domain_scale])) first_tone = range_tones[-1] range_tones = [first_tone] + range_tones[:-1] # Determine the tonality of the range range_tonality = Tonality.find_tonality(range_tones) return tonal_map, range_tonality
def test_inversion(self): print('test_inversion') ctype = 'PPPP' answers = ['C, F, Bb, Eb, Ab PPPP', 'F, C, Bb, Eb, Ab PPPP', 'Bb, C, F, Eb, Ab PPPP', 'Eb, C, F, Bb, Ab PPPP', 'Ab, C, F, Bb, Eb PPPP' ] diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C")) for i, a in zip(range(1, 6), answers): template = QuartalChordTemplate.parse('qC' + ctype + '@' + str(i)) chord = template.create_chord(diatonic_tonality) print(chord) tones = chord.tones s = '{0} {1}'.format(', '.join(tone[0].diatonic_symbol for tone in tones), chord.chord_type) print(s) assert s == a, '{0} != {1}'.format(s, a)
def test_check_chromatics_on_pentatonic(self): t_domain = Tonality.create(ModalityType.MajorPentatonic, DiatonicTone('E')) # E F# G# B C# E r = PitchRange.create('E:1', 'E:7') f = DiatonicPitchReflectionFunction( t_domain, DiatonicPitch(4, DiatonicToneCache.get_tone('G#')), r, FlipType.CenterTone) TestFlipOnTonality.print_map('test_check_chromatics_on_pentatonic', f) t = f.tonal_function assert 'G#' == t['G#'].diatonic_symbol assert 'F#' == t['B'].diatonic_symbol assert 'E' == t['C#'].diatonic_symbol assert 'B' == t['F#'].diatonic_symbol assert 'C#' == t['E'].diatonic_symbol assert 'E:4' == str(f['C#:5']) assert 'F#:4' == str(f['B:4']) assert 'G#:4' == str(f['G#:4']) assert 'B:4' == str(f['F#:4']) assert 'C#:5' == str(f['E:4']) assert 'E#:5' == str(f['C:4']) assert 'D#:5' == str(f['D:4']) assert 'B#:4' == str(f['F:4']) assert 'G##:4' == str( f['G:4']) # Note this and next are not symmetrical! assert 'G:4' == str(f['A#:4']) assert 'F##:4' == str(f['A:4']) assert 'E##:5' == str(f['Cb:4']) assert 'D##:5' == str(f['Db:4']) assert 'C##:5' == str(f['Eb:4']) assert 'B##:4' == str(f['Fb:4']) assert 'G###:4' == str(f['Gb:4']) assert 'F###:4' == str( f['Ab:4'] ) # Very interesting case!!! closest is G#, but need F# to get to G# assert 'F##:4' == str(f['Bb:4']) assert 'F:4' == str(f['B#:4']) assert 'D:5' == str(f['D#:4']) assert 'C:5' == str(f['E#:4']) assert 'G:4' == str(f['A#:4'])
def test_C_pentatonic(self): print('test_C_pentatonic: C-Pentatonic, variable cue') domain_tonality = Tonality.create(ModalityType.MajorPentatonic, DiatonicToneCache.get_tone('C')) tones = domain_tonality.annotation[:-1] cue_tone = tones[1] f = ChromaticTonalReflectionFunction(domain_tonality, cue_tone, FlipType.CenterTone) TestChromaticTonalReflectionFunction.print_map( domain_tonality, f, cue_tone.diatonic_symbol) answers = ['E', 'D', 'C', 'A', 'G'] for tone, i in zip(tones, range(0, 5)): assert f[tone] == DiatonicToneCache.get_tone(answers[i]), \ 'f[{0}]={1} != {2}'.format(tone.diatonic_symbol, f[tone].diatonic_symbol, DiatonicToneCache.get_tone(answers[i]).diatonic_symbol)
def test_simple_pitch_function(self): t_domain = Tonality.create(ModalityType.Major, DiatonicTone('E')) cycles = [['E', 'G#', 'A', 'C#'], ('F#', 'D#')] permutation_function = TonalityPermutationFunction.create( t_domain, cycles) r = PitchRange.create('E:3', 'E:7') f = TonalityPitchFunction(permutation_function, ('E:4', 'E:5'), r) TestTonalityPitchFunction.print_map('test_simple_pitch_fnction', f) assert 'G#:5' == str(f['E:4']) assert 'D#:6' == str(f['F#:4']) assert 'A:5' == str(f['G#:4']) assert 'C#:6' == str(f['A:4']) assert 'B:5' == str(f['B:4']) assert 'E:5' == str(f['C#:5']) assert 'F#:5' == str(f['D#:5'])