New package: Harmonic toolkit for SuperCollider

Hi friends!

I’ve published a new supercollider package for harmonic hacking.

Use it to easily turn a melody into a series of chords, or some chords into arpeggios. Or both. Or other kinds of harmonic shenanigans.

It makes it a lot simpler to work with chords, harmonies and arpeggios. It makes it so much simpler and easier to think harmonically in SC.

:dollar: SUPPORT :dollar: If you find this useful, please consider buying me a coffee. See the link in the github repo:

10 Likes

Great stuff! I like the very basic scope and limiting named chords to 7ths and intervals, but then allowing custom harmonies. Dealing with harmony can be such a chore sometimes in SC

ooooo this is right up my alley!

I seem to be having trouble getting started tho. I get this error when trying to create a Harmony instance, e.g. var h = Harmony.new(\major);

error message
ERROR: Message 'isSymbol' not understood.
Perhaps you misspelled 'asSymbol', or meant to call 'isSymbol' on another receiver?
RECEIVER:
   Symbol 'major'
ARGS:
KEYWORD ARGUMENTS:
CALL STACK:
	DoesNotUnderstandError:reportError
		arg this = <instance of DoesNotUnderstandError>
	Nil:handleError
		arg this = nil
		arg error = <instance of DoesNotUnderstandError>
	Thread:handleError
		arg this = <instance of Thread>
		arg error = <instance of DoesNotUnderstandError>
	Object:throw
		arg this = <instance of DoesNotUnderstandError>
	Object:doesNotUnderstand
		arg this = 'major'
		arg selector = 'isSymbol'
		arg args = [*0]
		arg kwargs = [*0]
	Harmony:init
		arg this = <instance of Harmony>
		arg intervals = 'major'
	< closed FunctionDef >
		var h = nil
	Interpreter:interpretPrintCmdLine
		arg this = <instance of Interpreter>
		var res = nil
		var func = <instance of Function>
		var code = "var h = Harmony.new(\major);"
		var doc = nil
		var ideClass = <instance of Meta_ScIDE>
	Process:interpretPrintCmdLine
		arg this = <instance of Main>
^^ ERROR: Message 'isSymbol' not understood.
Perhaps you misspelled 'asSymbol', or meant to call 'isSymbol' on another receiver?
RECEIVER: major

It’s most likely something I’m doing wrong but would very much appreciate any guidance :heart:

i had this same issue. see deps. i already had wslib, so i installed fosc, JoshMisc and after recompile it worked ok! :wink:

1 Like

that did the trick, thank you!

is the expectation that those dependencies should be installed automatically when installing the quark? Or is that something I have to check manually when installing a quark?

Feel free to point me somewhere else as I don’t want to derail this thread. :hugs:

Thanks!!!

Hey Kev, yes I don’t know why they aren’t installing automatically. But I just updated the code to remove the dependency. Please try again

oh i should have checked the github issues first! thanks for the link.

I’m happy to test but I had manually installed the dependencies listed in the harmonics.quark file as @igormpc helpfully suggested and all is good. I’ll follow up in the github issue to see what i can do to help test the update.

…if I can stop listening to the Ambient Machine example haha :smiling_face_with_three_hearts:

1 Like

This is good stuff! Although the adjective “harmonic” may be a bit ambiguous in this context (harmonic as in overtones & simple harmonic oscillator is probably closer to the computer music thinking than harmonic vs. melodic components of music). “harmony toolkit” would prob be better?

If ever you want to extend this to dealing with chord progressions rather than single chords, I’m happy to help, I’ve got a degree in this kind of reactionary music theory so I have ~eXpErTiSe~.

a bit offtopic but here’s maybe a somewhat related question:

I’ve been wondering if there are any quarks or extensions that deal with note and scale degree naming. I’m pretty quick with midi note numbers and that’s what I end up defaulting to, but it would be nice to have something similar to lilypond’s mode of note entry.
(E.g. some way of entering note names like C#7 or fis’’ or sol bémol 3).

Might try to write something like this myself but I suspect this exists already?

(Another thing that irks me about sc is the zero-based scale degree handling. I usually end up writing something like \degree, Pseq([1,2,3,4,5]) - 1 to get back to something more rooted in tonal practice, and obviously it would be easy to define an event key that serves as a wrapper for 0-based degrees…
All of this isn’t so much of an issue in non-tonal contexts, but all tonal pedagogies I am aware of count the tonic as 1, not 0.)

I’d be happy to get your expertise involved :slight_smile:

What did you have in mind for chord progressions? Happy to hear some ideas!

And my Monolithic package has this thing you talk about for note names.

This allows doing eg

60.midiNoteName
-> C4

and

"C4".asMidiNoteNumber
-> 60
1 Like

I hope it’s fixed now

What did you have in mind for chord progressions?

Sort of depends on the repertoire. Thinking basic jazz stuff (ii - V - i etc.), some sequences, maybe some of the more common partimento/figured bass patterns; for more pop/rock oriented stuff there’s a nice collection in Christopher Doll’s 2017 book that I can look over again. And also some of the haunted house clichés that keep coming up in film music, e.g. Em to Ab (“hexatonic pole”, etc.).
(oh and the omnipresent vi IV V I permutations would be another good candidate.)

I guess there’s a bit of a caveat here in somuch as this might be taken to suggest that these progressions are somehow more “right” than whatever harmonies folks might come up by themselves. Especially if people just mindlessly copypaste things…

And then there’s also the issue of voice leading, which is more or of an algorithmic challenge. To some degree that’s easy to automate, especially if it’s just transposition and possibly inversion of predefined patterns; not so easy if it’s supposed to be between arbitrary chords because to decide it you need context (stylistic and tonal).

I wonder if maybe some of the other programs out there (say openmusic, or some max extension, maybe bach?) already have something like that, so it’d be worth checking out how they handle that.

Looking forward to trying this out!

I think one way around this is, it should be very very easy to add custom chords/ progressions either on a piece by piece basis, or globally forever… The SC tuning/scale libraries might be a cautionary tale (at least I still never remember how to use them properly or make new ones… And the list of built in scales/tunings, with entries like “Egyptian” up against the complete list of western modes, demonstrates how tricky a curated selection can be especially if it aims for universality)

And speaking of tunings, does this library consider the possibility of anything other than 12 semitones per octave?

Re voice leading, at least being able to specify inversions seems essential and easy… (Maybe the library already has this?)

Em, there are various conventions:

  • Helmholtz notation
  • Scientific Pitch Notation
  • Yamaha’s Pitch Notation

I worked for SPN with microtonality a bit, but there is a typo, and I should rework it:

It would be great if SuperCollider supported a pitch name convention without any quark, including the following:

  • Helmholtz notation (midipitchnumber 60 = c1 or c’)
  • Scientific Pitch Notation (midipitchnumber 60 = c4)
  • Yamaha’s Pitch Notation (midipitchnumber 60 = c3)
  • pitchclass
  • and so on…

This was already discussed in 2022 or 2023. At that time, implementing this in a Quark was recommended. I mention this again because I see a similar implementation here again…

1 Like

I think I have a good idea for chord progression parsing. Will make a branch on the repo now!

NEW VERSION: Chord progressions

The toolkit now supports working with chord progressions as discussed above.

To update, run Quarks.update("HarmonicToolkitSC"). Then recompile.

Here’s a pattern example:

(
s.waitForBoot{
    Pbind(
        \midinote, PChordProgression(
            chords: "I V vi IV", 
            midiNoteOffset: 48,
            arpStyle: \chords,
            repeats: inf
        ),
        \dur, 0.25,
    ).play
}
)

Behind the scenes this uses PHarmony so you can arpeggiate your chord progression as well:

(
s.waitForBoot{
    Pbind(
        \midinote, PChordProgression(
            chords: "I V vi IV", 
            midiNoteOffset: 48,
            arpStyle: \updown,
            repeats: inf
        ),
        \dur, 0.125,
    ).play
}
)
2 Likes

Nice! Works like a charm and chord progressions is a great addition.

Since I already had everything installed, I had to uninstall, recompile and reboot before everything worked. But a clean install should work as documented now.