/usr/share/pyshared/pyknon/simplemusic.py is in python-pyknon 1.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | """
A simple numeric library for music computation.
This module is good for teaching, demonstrations, and quick hacks. To
generate actual music you should use the music module.
"""
from __future__ import division
from itertools import combinations, chain
from fractions import Fraction
def mod12(n):
return n % 12
def interval(x, y):
return mod12(x - y)
def interval_class(x, y):
return min(interval(x, y), interval(y, x))
def intervals(notes):
return [interval_class(y, x) for x,y in zip(notes, rotate(notes)[:-1])]
def all_intervals(notes):
intervals_list = [intervals(n) for n in combinations(sorted(notes), 2)]
return sorted(chain.from_iterable(intervals_list))
def transposition(notes, index):
return [mod12(n + index) for n in notes]
def transposition_startswith(notes, start):
return transposition(notes, start - notes[0])
def is_related_by_transposition(notes1, notes2):
rotations = rotate_set(sorted(notes2))
transpositions = [transposition(sorted(notes1), n) for n in range(0, 12)]
return any(True for rotation in rotations if rotation in transpositions)
def inversion(notes, index=0):
return [mod12(index - n) for n in notes]
def inversion_startswith(notes, start):
transp = transposition_startswith(notes, 0)
return transposition_startswith(inversion(transp), start)
def inversion_first_note(notes):
return inversion(notes, 2 * notes[0])
def rotate(item, n=1):
modn = n % len(item)
return item[modn:] + item[0:modn]
def rotate_set(notes):
return [rotate(notes, x) for x in range(0, len(notes))]
def retrograde(notes):
return list(reversed(notes))
def note_name(number):
notes = "C C# D D# E F F# G G# A A# B".split()
return notes[mod12(number)]
def notes_names(notes):
return [note_name(x) for x in notes]
def accidentals(note_string):
acc = len(note_string[1:])
if "#" in note_string:
return acc
elif "b" in note_string:
return -acc
else:
return 0
def name_to_number(note_string):
notes = "C . D . E F . G . A . B".split()
name = note_string[0:1].upper()
number = notes.index(name)
acc = accidentals(note_string)
return mod12(number + acc)
def name_to_diatonic(note_string):
notes = "C D E F G A B".split()
name = note_string[0:1].upper()
return notes.index(name)
def note_duration(note_value, unity, tempo):
return (60.0 * note_value) / (tempo * unity)
def dotted_duration(duration, dots):
ratio = Fraction(1, 2)
return duration * (1 - ratio ** (dots + 1)) / ratio
def durations(notes_values, unity, tempo):
return [note_duration(nv, unity, tempo) for nv in notes_values]
def get_quality(diatonic_interval, chromatic_interval):
if diatonic_interval in [0, 3, 4]:
quality_map = ["Diminished", "Perfect", "Augmented"]
else:
quality_map = ['Diminished', 'Minor', 'Major', 'Augmented']
index_map = [-1, 0, 2, 4, 6, 7, 9]
return quality_map[chromatic_interval - index_map[diatonic_interval]]
def interval_name(note1, note2):
quantities = ["Unison", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh"]
n1, n2 = name_to_number(note1), name_to_number(note2)
d1, d2 = name_to_diatonic(note1), name_to_diatonic(note2)
chromatic_interval = interval(n2, n1)
diatonic_interval = (d2 - d1) % 7
quantity_name = quantities[diatonic_interval]
quality_name = get_quality(diatonic_interval, chromatic_interval)
return "%s %s" % (quality_name, quantity_name)
|