Note Names / Pitch Classes

Maybe something like this:

(That’s an attempt to simulate the haskell code (addInterval) above to a minimal sc snippet)

(

~noteNames = [ \C, \D, \E, \F, \G, \A, \B ];

~accidentals = [ \doubleFlat, \flat, \natural, \sharp, \doubleSharp ];

// Returns semitones value of just the note (ignoring accidental)
~noteToSemitones = { |noteName|
    switch(noteName)
    {\C} { 0 }
    {\D }{ 2 }
    {\E} { 4 }
    {\F} { 5 }
    {\G} { 7 }
    {\A} { 9 }
    {\B} { 11 };
};

~pitchClassToSemitones = { |note|
    var base;
    var adjust;
  
    base = ~noteToSemitones.(note[0]);

    adjust = switch (note[1])
    {\doubleFlat} { -2 }
    {\flat} { -1 }
    {\natural} { 0 }
    {\sharp} { 1 }
    {\doubleSharp} { 2 };
    
    base + adjust;
};

~intervalToSemitones = { |interval|
    var base;
    var adjust;
    
    base = switch(interval[0], 
        \unison, { 0 },
        \second, { 2 },
        \third, { 4 },
        \fourth, { 5 },
        \fifth, { 7 },
        \sixth, { 9 },
        \seventh, { 11 },
        \octave, { 12 },
        { 0 }
    );
    
    adjust = switch(interval[1], 
        \perfect, { 0 },
        \major, { 0 },
        \minor, { -1 },
        \augmented, { 1 },
        \diminished, { -1 },
        { 0 }
    );
    
    base + adjust;
};

~addInterval = { |pitchClass, interval|
    var totalSemitones;
    var newSize;
    var newNoteValue;
    var newNote;
    var newAccidental; var diff ;
    
    var noteNames = [ \C, \D, \E, \F, \G, \A, \B ];
    
    totalSemitones = (~pitchClassToSemitones.([pitchClass[0], pitchClass[1]]) + ~intervalToSemitones.(interval)).mod(12);
    
    newSize = switch(interval[0]) 
    {\unison} { 0 }
    {\second} { 1 }
    {\third} { 2 }
    {\fourth} { 3 }
    {\fifth} { 4 }
    {\sixth} { 5 }
    {\seventh} { 6 }
    {\octave} { 7 };
    
    newNoteValue = (noteNames.indexOf(pitchClass[0]) + newSize).mod(7);
    newNote = noteNames[newNoteValue];

    diff = totalSemitones - ~noteToSemitones.(newNote);
    
    newAccidental = switch(diff)
    { -2 } { \doubleFlat }
    { -1 } { \flat }
    { 0 } { \natural }
    { 1 } { \sharp }
    { 2 } { \doubleSharp };

    [newNote, newAccidental];
};

)

Example:

~c = [\C, \natural];
~perfectFourth = [\fourth, \perfect];

~resultingPitch = ~addInterval.(~c, ~perfectFourth);
// -> [ F, natural ]

~addInterval.([\F, \sharp], [\third, \major]);
// -> [ A, sharp ]


~addInterval.([\B, \sharp], [\third, \minor]);
// -> [ D, sharp ]

~addInterval.([\F, \flat], [\sixth, \major]);
-> [ D, flat ]