Ejemplo n.º 1
0
    def set_note(self, name='C', octave=4, dynamics={}):
        """Set the note to name in octave with dynamics.

        Return the objects if it succeeded, raise an NoteFormatError
        otherwise.
        """
        dash_index = name.split('-')
        if len(dash_index) == 1:
            if notes.is_valid_note(name):
                self.name = name
                self.octave = octave
                self.dynamics = dynamics
                return self
            else:
                raise NoteFormatError("The string '%s' is not a valid "
                                      "representation of a note in mingus" %
                                      name)
        elif len(dash_index) == 2:
            if notes.is_valid_note(dash_index[0]):
                self.name = dash_index[0]
                self.octave = int(dash_index[1])
                self.dynamics = dynamics
                return self
            else:
                raise NoteFormatError("The string '%s' is not a valid "
                                      "representation of a note in mingus" %
                                      name)
        return False
Ejemplo n.º 2
0
def get_notes(key='C'):
    """Return an ordered list of the notes in this natural key.

    Examples:
    >>> get_notes('F')
    ['F', 'G', 'A', 'Bb', 'C', 'D', 'E']
    >>> get_notes('c')
    ['C', 'D', 'Eb', 'F', 'G', 'Ab', 'Bb']
    """
    if _key_cache.has_key(key):
        return _key_cache[key]
    if not is_valid_key(key):
        raise NoteFormatError("unrecognized format for key '%s'" % key)
    result = []

    # Calculate notes
    altered_notes = map(operator.itemgetter(0),
            get_key_signature_accidentals(key))

    if get_key_signature(key) < 0:
        symbol = 'b'
    elif get_key_signature(key) > 0:
        symbol = '#'

    raw_tonic_index = base_scale.index(key.upper()[0])

    for note in islice(cycle(base_scale), raw_tonic_index, raw_tonic_index+7):
        if note in altered_notes:
            result.append('%s%s' % (note, symbol))
        else:
            result.append(note)
    
    # Save result to cache
    _key_cache[key] = result
    return result
Ejemplo n.º 3
0
def relative_minor(key):
    """Return the relative minor of a major key.

    Example:
    >>> relative_minor('C')
    'a'
    """
    for couple in keys:
        if key == couple[0]:
            return couple[1]
    raise NoteFormatError("'%s' is not a major key" % key)
Ejemplo n.º 4
0
def get_key_signature(key='C'):
    """Return the key signature.

    0 for C or a, negative numbers for flat key signatures, positive numbers
    for sharp key signatures.
    """
    if not is_valid_key(key):
        raise NoteFormatError("unrecognized format for key '%s'" % key)

    for couple in keys:
        if key in couple:
            accidentals = keys.index(couple) - 7
            return accidentals
Ejemplo n.º 5
0
 def __init__(self, name='C', octave=4, dynamics={}):
     if type(name) == str:
         self.set_note(name, octave, dynamics)
     elif hasattr(name, 'name'):
         # Hardcopy Note object
         self.set_note(name.name, name.octave, name.dynamics)
         if hasattr(name, 'channel'):
             self.channel = name.channel
         if hasattr(name, 'velocity'):
             self.velocity = name.velocity
     elif type(name) == int:
         self.from_int(name)
     else:
         raise NoteFormatError("Don't know what to do with name object: "
                               "'%s'" % name)
Ejemplo n.º 6
0
def note_to_int(note):
    """Convert notes in the form of C, C#, Cb, C##, etc. to an integer in the
    range of 0-11.

    Throw a NoteFormatError exception if the note format is not recognised.
    """
    if is_valid_note(note):
        val = _note_dict[note[0]]
    else:
        raise NoteFormatError("Unknown note format '%s'" % note)

    # Check for '#' and 'b' postfixes
    for post in note[1:]:
        if post == 'b':
            val -= 1
        elif post == '#':
            val += 1
    return val % 12
Ejemplo n.º 7
0
def reduce_accidentals(note):
    """Reduce any extra accidentals to proper notes.

    Example:
    >>> reduce_accidentals('C####')
    'E'
    """
    val = note_to_int(note[0])
    for token in note[1:]:
        if token == 'b':
            val -= 1
        elif token == '#':
            val += 1
        else:
            raise NoteFormatError("Unknown note format '%s'" % note)
    if val >= note_to_int(note[0]):
        return int_to_note(val % 12)
    else:
        return int_to_note(val % 12, 'b')
Ejemplo n.º 8
0
def from_shorthand(shorthand_string, slash=None):
    """Take a chord written in shorthand and return the notes in the chord.

    The function can recognize triads, sevenths, sixths, ninths, elevenths,
    thirteenths, slashed chords and a number of altered chords.

    The second argument should not be given and is only used for a recursive
    call when a slashed chord or polychord is found.

    See http://tinyurl.com/3hn6v8u for a nice overview of chord patterns.

    Examples:
    >>> from_shorthand('Amin')
    ['A', 'C', 'E']
    >>> from_shorthand('Am/M7')
    ['A', 'C', 'E', 'G#']
    >>> from_shorthand('A')
    ['A', 'C#', 'E']
    >>> from_shorthand('A/G')
    ['G', 'A', 'C#', 'E']
    >>> from_shorthand('Dm|G')
    ['G', 'B', 'D', 'F', 'A']

    Recognised abbreviations: the letters "m" and "M" in the following
    abbreviations can always be substituted by respectively "min", "mi" or
    "-" and "maj" or "ma".
    
    Example:
    >>> from_shorthand('Amin7') == from_shorthand('Am7')
    True

    Triads: 'm', 'M' or '', 'dim'

    Sevenths: 'm7', 'M7', '7', 'm7b5', 'dim7', 'm/M7' or 'mM7'

    Augmented chords: 'aug' or '+', '7#5' or 'M7+5', 'M7+', 'm7+', '7+'

    Suspended chords: 'sus4', 'sus2', 'sus47' or '7sus4', 'sus', '11',
    'sus4b9' or 'susb9'

    Sixths: '6', 'm6', 'M6', '6/7' or '67', '6/9' or '69'

    Ninths: '9' or 'add9', 'M9', 'm9', '7b9', '7#9'

    Elevenths: '11' or 'add11', '7#11', 'm11'

    Thirteenths: '13' or 'add13', 'M13', 'm13'

    Altered chords: '7b5', '7b9', '7#9', '67' or '6/7'

    Special: '5', 'NC', 'hendrix'
    """
    # warning reduce??
    if type(shorthand_string) == list:
        res = []
        for x in shorthand_string:
            res.append(from_shorthand(x))
        return res
    if shorthand_string in ['NC', 'N.C.']:
        return []

    # Shrink shorthand_string to a format recognised by chord_shorthand
    shorthand_string = shorthand_string.replace('min', 'm')
    shorthand_string = shorthand_string.replace('mi', 'm')
    shorthand_string = shorthand_string.replace('-', 'm')
    shorthand_string = shorthand_string.replace('maj', 'M')
    shorthand_string = shorthand_string.replace('ma', 'M')

    # Get the note name
    if not notes.is_valid_note(shorthand_string[0]):
        raise NoteFormatError("Unrecognised note '%s' in chord '%s'"\
             % (shorthand_string[0], shorthand_string))
    name = shorthand_string[0]

    # Look for accidentals
    for n in shorthand_string[1:]:
        if n == '#':
            name += n
        elif n == 'b':
            name += n
        else:
            break

    # Look for slashes and polychords '|'
    slash_index = -1
    s = 0
    rest_of_string = shorthand_string[len(name):]
    for n in rest_of_string:
        if n == '/':
            slash_index = s
        elif n == '|':
            # Generate polychord
            return from_shorthand(
                shorthand_string[:len(name) + s],
                from_shorthand(shorthand_string[len(name) + s + 1:]))
        s += 1

    # Generate slash chord
    if slash_index != -1 and rest_of_string not in ['m/M7', '6/9', '6/7']:
        res = shorthand_string[:len(name) + slash_index]
        return from_shorthand(shorthand_string[:len(name) + slash_index],
                              shorthand_string[len(name) + slash_index + 1:])
    shorthand_start = len(name)

    short_chord = shorthand_string[shorthand_start:]
    if short_chord in chord_shorthand:
        res = chord_shorthand[short_chord](name)
        if slash != None:
            # Add slashed chords
            if type(slash) == str:
                if notes.is_valid_note(slash):
                    res = [slash] + res
                else:
                    raise NoteFormatError(
                        "Unrecognised note '%s' in slash chord'%s'" %
                        (slash, slash + shorthand_string))
            elif type(slash) == list:
                # Add polychords
                r = slash
                for n in res:
                    if n != r[-1]:
                        r.append(n)
                return r
        return res
    else:
        raise FormatError('Unknown shorthand: %s' % shorthand_string)
Ejemplo n.º 9
0
    def __init__(self, note, octaves):
        if note.islower():
            raise NoteFormatError("Unrecognised note '%s'" % note)

        self.tonic = note
        self.octaves = octaves