     @abbrs ?= [@abbr]
     @abbrs = @abbrs.split(/s/) if typeof @abbrs == 'string'
     @abbr ?= @abbrs[0]
-    if @rootPitch?
-      @rootName or= NoteNames[@rootPitch]
+
+    @rootName or= NoteNames[@rootPitch] if @rootPitch?
     if @rootName?
-      @rootPitch ?= parsePitchClass(@rootName)
+      @rootPitch ?=
+        if @rootName.match(/\d/) then pitchFromScientificNotation(@rootName) else parsePitchClass(@rootName)
+      @pitches = (pitch + @rootPitch for pitch in @pitchClasses)
       rootlessAbbr = @abbr
       rootlessFullName = @fullName
       Object.defineProperty this, 'name', get: -> "#{@rootName}#{rootlessAbbr}"
       Object.defineProperty this, 'fullName', get: -> "#{@rootName} #{rootlessFullName}"
+
     degrees = (1 + 2 * i for i in [0..@pitchClasses.length])
     degrees[1] = {'Sus2':2, 'Sus4':4}[@name] || degrees[1]
     degrees[3] = 6 if @name.match /6/
+
     @components = for pc, pci in @pitchClasses
       name = IntervalNames[pc]
       degree = degrees[pci]

    return this

  @find: (name) ->
    match = name.match(/^([a-gA-G][#b♯♭]*)(.*)$/)
    throw new Error("#{name} is not a chord name") unless match
    [noteName, chordName] = match[1...]
    throw new Error("#{name} is not a chord name") unless Chords[chordName]
    return Chords[chordName].at(noteName)

  @fromPitches: (pitches) ->
    root = pitches[0]

  [naturalName, accidentals] = match[1...]
  pitch = SharpNoteNames.indexOf(naturalName.toUpperCase())
  pitch += AccidentalValues[c] for c in accidentals
  return pitch

midi2name = (number) ->
  "#{NoteNames[(number + 12) % 12]}#{Math.floor((number - 12) / 12)}"

name2midi = (name) ->
  throw new Error "#{name} is not a note name" unless m = name.toUpperCase().match(/^([A-G])([♯#♭b𝄪𝄫]*)(\d+)/)
  [noteName, accidentals, octave] = m.slice(1)
  pitch = NoteNames.indexOf(noteName)
  pitch += AccidentalValues[c] for c in accidentals
  pitch += 12 * Number(octave)
  return pitch


