Skip to content

Scales

scale(tonic_note, scale_type)

Generate a scale based on a tonic and a scale type.

Parameters:

Name Type Description Default
tonic_note str

The musical note serving as the tonic of the scale.

required
scale_type str

The type of the scale, e.g., major or minor.

required

Returns:

Type Description
dict[str, list[str]]

A dictionary containing the notes of the scale and their corresponding degrees.

Raises:

Type Description
ValueError

If the tonic note is invalid.

KeyError

If the scale mode does not exist or has not been implemented.

Examples:

>>> scale("C", "major")
{'notes': ['C', 'D', 'E', 'F', 'G', 'A', 'B'], 'degrees': ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII']}
>>> scale("A", "minor")
{'notes': ['A', 'B', 'C', 'D', 'E', 'F', 'G'], 'degrees': ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII']}
Source code in melodica_notes/scales.py
 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
def scale(tonic_note: str, scale_type: str) -> dict[str, list[str]]:
    """
    Generate a scale based on a tonic and a scale type.

    Args:
        tonic_note (str): The musical note serving as the tonic of the scale.
        scale_type (str): The type of the scale, e.g., major or minor.

    Returns:
        A dictionary containing the notes of the scale and their corresponding degrees.

    Raises:
        ValueError: If the tonic note is invalid.
        KeyError: If the scale mode does not exist or has not been implemented.

    Examples:
        >>> scale("C", "major")
        {'notes': ['C', 'D', 'E', 'F', 'G', 'A', 'B'], 'degrees': ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII']}

        >>> scale("A", "minor")
        {'notes': ['A', 'B', 'C', 'D', 'E', 'F', 'G'], 'degrees': ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII']}
    """
    tonic_note = tonic_note.upper()
    notes = SHARP_NOTES

    if len(tonic_note) > 1:
        tonic_note = tonic_note[0] + tonic_note[1].lower()
        if tonic_note[1] == "b":
            notes = FLAT_NOTES

    try:
        intervals = SCALES[scale_type]
        tonic_position = notes.index(tonic_note)
    except ValueError:
        raise ValueError(
            f"This musical note does not exist. Please use one of these: {NOTES}")
    except KeyError:
        raise KeyError(
            "This scale mode does not exist or has not been implemented. "
            f"Please use one of these: {list(SCALES.keys())}"
        )

    temp = []

    for interval in intervals:
        note = (tonic_position + interval) % 12
        temp.append(notes[note])

    return {"notes": temp, "degrees": ["I", "II", "III", "IV", "V", "VI", "VII"]}