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 ]