code: def key_to_notes(
      key: str, *, unicode: bool = True, natural: bool = False
  ) -> List[str]:
      """List all 12 note names in the chromatic scale, as spelled according to
      a given key (major or minor) or mode (see below for details and accepted abbreviations).
  
      This function exists to resolve enharmonic equivalences between different
      spellings for the same pitch (e.g. C♯ vs D♭), and is primarily useful when producing
      human-readable outputs (e.g. plotting) for pitch content.
  
      Note names are decided by the following rules:
  
      1. If the tonic of the key has an accidental (sharp or flat), that accidental will be
         used consistently for all notes.
  
      2. If the tonic does not have an accidental, accidentals will be inferred to minimize
         the total number used for diatonic scale degrees.
  
      3. If there is a tie (e.g., in the case of C:maj vs A:min), sharps will be preferred.
  
      Parameters
      ----------
      key : string
          Must be in the form TONIC:key.  Tonic must be upper case (``CDEFGAB``),
          key must be lower-case
          (``major``, ``minor``, ``ionian``, ``dorian``, ``phrygian``, ``lydian``, ``mixolydian``, ``aeolian``, ``locrian``).
  
          The following abbreviations are supported for the modes: either the first three letters of the mode name
          (e.g. "mix") or the mode name without "ian" (e.g. "mixolyd").
  
          Both ``major`` and ``maj`` are supported as mode abbreviations.
  
          Single and multiple accidentals (``b!♭`` for flat, ``#♯`` for sharp, ``𝄪𝄫`` for double-accidentals, or any combination thereof) are supported.
  
          Examples: ``C:maj, C:major, Dbb:min, A♭:min, D:aeo, E𝄪:phryg``.
  
      unicode : bool
          If ``True`` (default), use Unicode symbols (♯𝄪♭𝄫)for accidentals.
  
          If ``False``, Unicode symbols will be mapped to low-order ASCII representations::
  
              ♯ -> #, 𝄪 -> ##, ♭ -> b, 𝄫 -> bb, ♮ -> n
  
      natural : bool
          If ``True'', mark natural accidentals with a natural symbol (♮).
  
          If ``False`` (default), do not print natural symbols.
  
          For example, `note_to_degrees('D:maj')[0]` is `C` if `natural=False` (default) and `C♮` if `natural=True`.
  
      Returns
      -------
      notes : list
          ``notes[k]`` is the name for semitone ``k`` (starting from C)
          under the given key.  All chromatic notes (0 through 11) are
          included.
  
      See Also
      --------
      midi_to_note
  
      Examples
      --------
      `C:maj` will use all sharps
  
      >>> librosa.key_to_notes('C:maj')
      ['C', 'C♯', 'D', 'D♯', 'E', 'F', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B']
  
      `A:min` has the same notes
  
      >>> librosa.key_to_notes('A:min')
      ['C', 'C♯', 'D', 'D♯', 'E', 'F', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B']
  
      `A♯:min` will use sharps, but spell note 0 (`C`) as `B♯`
  
      >>> librosa.key_to_notes('A#:min')
      ['B♯', 'C♯', 'D', 'D♯', 'E', 'E♯', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B']
  
      `G♯:maj` will use a double-sharp to spell note 7 (`G`) as `F𝄪`:
  
      >>> librosa.key_to_notes('G#:maj')
      ['B♯', 'C♯', 'D', 'D♯', 'E', 'E♯', 'F♯', 'F𝄪', 'G♯', 'A', 'A♯', 'B']
  
      `F♭:min` will use double-flats
  
      >>> librosa.key_to_notes('Fb:min')
      ['D𝄫', 'D♭', 'E𝄫', 'E♭', 'F♭', 'F', 'G♭', 'A𝄫', 'A♭', 'B𝄫', 'B♭', 'C♭']
  
      `G:loc` uses flats
  
      >>> librosa.key_to_notes('G:loc')
      ['C', 'D♭', 'D', 'E♭', 'E', 'F', 'G♭', 'G', 'A♭', 'A', 'B♭', 'B']
  
      If `natural=True`, print natural accidentals.
  
      >>> librosa.key_to_notes('G:loc', natural=True)
      ['C', 'D♭', 'D♮', 'E♭', 'E♮', 'F', 'G♭', 'G', 'A♭', 'A♮', 'B♭', 'B♮']
  
      >>> librosa.key_to_notes('D:maj', natural=True)
      ['C♮', 'C♯', 'D', 'D♯', 'E', 'F♮', 'F♯', 'G', 'G♯', 'A', 'A♯', 'B']
  
      >>> librosa.key_to_notes('G#:maj', unicode = False, natural = True)
      ['B#', 'C#', 'Dn', 'D#', 'En', 'E#', 'F#', 'F##', 'G#', 'An', 'A#', 'B']
  
      """
      # Parse the key signature
      match = KEY_RE.match(key)
  
      if not match:
          raise ParameterError(f"Improper key format: {key:s}")
  
      pitch_map = {
          "C": 0,
          "D": 2,
          "E": 4,
          "F": 5,
          "G": 7,
          "A": 9,
          "B": 11,
      }
  
      tonic = match.group("tonic").upper()
      accidental = match.group("accidental")
  
      offset = sum([ACC_MAP[acc] for acc in accidental])
  
      if match.group("mode") or not match.group("scale"):
          equiv = __mode_to_key(key)
          return key_to_notes(equiv, unicode=unicode, natural=natural)
  
      scale = match.group("scale")[:3].lower()
  
      multiple = abs(offset) >= 2
  
      # If multiple accidentals, we use recursion, then cycle through so that the enharmonic equivalent of C is at the beginning again.
  
      if multiple:
          sign_map = {+1: "♯", -1: "♭"}
          additional_acc = sign_map[np.sign(offset)]
          intermediate_notes = key_to_notes(
              tonic + additional_acc * (abs(offset) - 1) + ":" + scale,
              natural=False,
          )
          notes = [
              __simplify_note(note, additional_acc)
              for note in intermediate_notes
          ]
          degrees = __note_to_degree(notes)
          notes = np.roll(notes, shift=-np.argwhere(degrees == 0)[0])
  
          notes = list(notes)
  
          if not unicode:
              translations = str.maketrans(
                  {"♯": "#", "𝄪": "##", "♭": "b", "𝄫": "bb", "♮": "n"}
              )
              notes = list(n.translate(translations) for n in notes)
  
          return notes
  
      # Determine major or minor
      major = scale == "maj"
  
      # calculate how many clockwise steps we are on CoF (== # sharps)
      if major:
          tonic_number = ((pitch_map[tonic] + offset) * 7) % 12
      else:
          tonic_number = ((pitch_map[tonic] + offset) * 7 + 9) % 12
  
      # Decide if using flats or sharps
      # Logic here is as follows:
      #   1. respect the given notation for the tonic.
      #      Sharp tonics will always use sharps, likewise flats.
      #   2. If no accidental in the tonic, try to minimize accidentals.
      #   3. If there's a tie for accidentals, use sharp for major and flat for minor.
  
      if offset < 0:
          # use flats explicitly
          use_sharps = False
  
      elif offset > 0:
          # use sharps explicitly
          use_sharps = True
  
      elif 0 <= tonic_number < 6:
          use_sharps = True
  
      elif tonic_number > 6:
          use_sharps = False
  
      # Basic note sequences for simple keys
      notes_sharp = [
          "C",
          "C♯",
          "D",
          "D♯",
          "E",
          "F",
          "F♯",
          "G",
          "G♯",
          "A",
          "A♯",
          "B",
      ]
      notes_flat = [
          "C",
          "D♭",
          "D",
          "E♭",
          "E",
          "F",
          "G♭",
          "G",
          "A♭",
          "A",
          "B♭",
          "B",
      ]
  
      # These apply when we have >= 6 sharps
      sharp_corrections = [
          (5, "E♯"),
          (0, "B♯"),
          (7, "F𝄪"),
          (2, "C𝄪"),
          (9, "G𝄪"),
          (4, "D𝄪"),
          (11, "A𝄪"),
      ]
  
      # These apply when we have >= 6 flats
      flat_corrections = [
          (11, "C♭"),
          (4, "F♭"),
          (9, "B𝄫"),
          (2, "E𝄫"),
          (7, "A𝄫"),
          (0, "D𝄫"),
      ]  # last would be (5, 'G𝄫')
  
      # Apply a mod-12 correction to distinguish B#:maj from C:maj
      n_sharps = tonic_number
      if tonic_number == 0 and tonic == "B":
          n_sharps = 12
  
      if use_sharps:
          # This will only execute if n_sharps >= 6
          for n in range(0, n_sharps - 6 + 1):
              index, name = sharp_corrections[n]
              notes_sharp[index] = name
  
          notes = notes_sharp
      else:
          n_flats = (12 - tonic_number) % 12
  
          # This will only execute if tonic_number <= 6
          for n in range(0, n_flats - 6 + 1):
              index, name = flat_corrections[n]
              notes_flat[index] = name
  
          notes = notes_flat
  
      # Apply natural signs to any note which has no other accidentals and does not appear in the scale for key.
      if natural:
          scale_notes = set(key_to_degrees(key))
          for place, note in enumerate(notes):
              if __note_to_degree(note) in scale_notes:
                  continue
              if len(note) == 1:
                  notes[place] = note + "♮"
  
      # Finally, apply any unicode down-translation if necessary
      if not unicode:
          translations = str.maketrans(
              {"♯": "#", "𝄪": "##", "♭": "b", "𝄫": "bb", "♮": "n"}
          )
          notes = list(n.translate(translations) for n in notes)
  
      return notes
  
imports: import re
  import numpy
  from numba import jit
  from collections import Counter
  from .intervals import INTERVALS
  from .._cache import cache
  from ..util.exceptions import ParameterError
  from typing import Dict, List, Iterable, Union, overload
  from ..util.decorators import vectorize
  from .._typing import _ScalarOrSequence, _FloatLike_co, _SequenceLike, _IterableLike
label_desc: Use image node_id 15 for calling a global function with example usage: key_to_notes(key) and returns: notes, key_to_notes, notes