def get_alto_score(candidate, beat): score = 0.0 low_thresh = parts.ALTO.max_low high_thresh = parts.ALTO.max_high score += threshold_encroachment_score(candidate, low_thresh, low_thresh + 4) score += threshold_encroachment_score(candidate, high_thresh, high_thresh - 4) score += preferred_register_score(candidate, high_thresh, high_thresh - 7) score += motion_tendency_score(candidate, beat, sequences.alto()) score += linear_motion_score(candidate, beat, sequences.alto()) score += flicker_avoidance_score(candidate, beat, sequences.alto()) return score
def get_all_transforms(start_position, end_position, max_subdivisions): satb = sequences.soprano(), sequences.alto(), sequences.tenor(), sequences.bass() pitches = [(sequence.pitch(start_position), sequence.pitch(end_position)) for sequence in satb] chord = chords.get(start_position) rhythm_set_groups = get_rhythm_sets(config.minimum_time_unit(), max_subdivisions, end_position - start_position) direction_set_groups = [direction_permutations(i) for i in range(1, max_subdivisions)] all_transforms = [] for i, (sequence, (start_pitch, end_pitch)) in enumerate(zip(satb[1:], pitches[1:])): # We can't (read: don't want to) transform to or from a rest; skip if the start or end pitch is a rest. if start_pitch == -1 or end_pitch == -1: all_transforms.append([[]]) continue high_thresh = min([p for p in pitches[i] if p != -1] + [sequence.part().max_high]) low_thresh = sequence.part().max_low if i == len(satb) - 1 else min(sequence.part().max_low, pitches[i - 1]) bounded_pitches = [pitch for pitch in chord.scale() if low_thresh <= pitch <= high_thresh] sequence_transforms = [] for i, direction_set_group in enumerate(direction_set_groups): pitch_sets = [group for direction_set in direction_set_group for group in pitch_sets_for_directions(bounded_pitches, start_pitch, end_pitch, direction_set)] trans = [StrongBeatPhrase(r, p) for p in pitch_sets for r in rhythm_set_groups[i]] sequence_transforms.extend(trans) all_transforms.append(sequence_transforms) product = list(itertools.product(*all_transforms)) return product
def get_candidate_matrix(beat, soprano_value): current_chord = chords.get(beat.start()) alto_candidates = sequences.alto().part().available_notes(current_chord) + [-1] tenor_candidates = sequences.tenor().part().available_notes(current_chord) + [-1] bass_candidates = sequences.bass().part().available_notes(current_chord) + [-1] return [g + [soprano_value] for g in combine_pitch_candidates(alto_candidates, tenor_candidates, bass_candidates) if parts_dont_cross(g, soprano_value)]
def score(self, beat, candidate): bass_score = get_bass_score(candidate[BASS_POSITION], beat) tenor_score = get_tenor_score(candidate[TENOR_POSITION], beat) alto_score = get_alto_score(candidate[ALTO_POSITION], beat) harmony_score = get_harmony_score(candidate, beat) duplicate_penalty = get_duplicate_penalty(candidate) rest_penalty = get_rest_penalty(candidate) motion_score = parallel_motion_score(candidate, beat, sequences.soprano(), sequences.alto(), sequences.tenor(), sequences.bass()) return sum([bass_score, tenor_score, alto_score, harmony_score, motion_score, rest_penalty, duplicate_penalty])
def test__get_all_transforms_minimal(self): fileloader.load(constants.TEST_MIDI + 'maj3_scalar.mid', False) chords.write('C') alto = sequences.alto() g4 = sequences.Note(alto, 0, 96, pitches.MIDI_VALUES['G4']) b4 = sequences.Note(alto, 96, 192, pitches.MIDI_VALUES['B4']) alto.add_entities(g4, b4) self.assertEqual(124, len(transforms.get_all_transforms(0, 96, 4)))
def test__get_motion_score(self): fileloader.load(constants.TEST_MIDI + 'parallel1.mid', False) soprano = sequences.soprano() tenor = sequences.RootSequence( read_pattern(constants.TEST_MIDI + 'parallel2.mid')[0]) irrelevant_pitch = 11 # [0] = alto, [1] = tenor, [2] = bass candidate = pitches.MIDI_VALUES['D5'], pitches.MIDI_VALUES[ 'A5'], irrelevant_pitch, self.assertEqual( 0.0, note_picker.parallel_motion_score(candidate, time.beat_at_index(0), soprano, sequences.alto(), tenor, sequences.bass())) self.assertEqual( vars.PARALLEL_MOVEMENT, note_picker.parallel_motion_score(candidate, time.beat_at_index(1), soprano, sequences.alto(), tenor, sequences.bass()))
def test__get_all_transforms(self): fileloader.load(constants.TEST_MIDI + 'maj3_scalar.mid', False) chords.write('C') alto = sequences.alto() tenor = sequences.tenor() bass = sequences.bass() g4_alto = sequences.Note(alto, 0, 96, pitches.MIDI_VALUES['G4']) b4_alto = sequences.Note(alto, 96, 192, pitches.MIDI_VALUES['B4']) e4_tenor = sequences.Note(tenor, 0, 96, pitches.MIDI_VALUES['E4']) g4_tenor = sequences.Note(tenor, 96, 192, pitches.MIDI_VALUES['G4']) c4_bass = sequences.Note(bass, 0, 96, pitches.MIDI_VALUES['C4']) e4_bass = sequences.Note(bass, 96, 192, pitches.MIDI_VALUES['E4']) alto.add_entities(g4_alto, b4_alto) tenor.add_entities(e4_tenor, g4_tenor) bass.add_entities(c4_bass, e4_bass) t = transforms.get_all_transforms(0, 96, 3) e = 1
print 'Selecting initial accompaniment...' picker = note_picker.NotePicker() keys = time.measures().keys() keys.sort() strong_beats = list(chain.from_iterable([time.measures()[key].strong_beats() for key in keys])) for i in range(len(strong_beats)): beat = strong_beats[i] pitches = picker.compute(beat) start = beat.start() end = config.song_length if beat.end() == config.song_length else strong_beats[i + 1].start() bass_note = sequences.Note(sequences.bass(), start, end, pitches[note_picker.BASS_POSITION]) tenor_note = sequences.Note(sequences.tenor(), start, end, pitches[note_picker.TENOR_POSITION]) alto_note = sequences.Note(sequences.alto(), start, end, pitches[note_picker.ALTO_POSITION]) sequences.bass().add_entities(bass_note) sequences.tenor().add_entities(tenor_note) sequences.alto().add_entities(alto_note) # ~~~~~~~~ Increase or decrease motion by grouping notes together or adding inter-beat motion ~~~~~~~~ for last_beat, this_beat in zip(strong_beats, strong_beats[1:]): t = transforms.get_all_transforms(last_beat.start(), this_beat.start(), 3) print 'yo' # motionizer = motion.Motionizer()