diff --git a/HelpSource/Classes/TonalUniverse.schelp b/HelpSource/Classes/TonalUniverse.schelp index d80faf7..c7b8105 100644 --- a/HelpSource/Classes/TonalUniverse.schelp +++ b/HelpSource/Classes/TonalUniverse.schelp @@ -1,10 +1,10 @@ TITLE:: TonalUniverse summary:: Set of tonalities and relations between them -categories:: Harmony +categories:: Harmony, Chords, Tonality DESCRIPTION:: -Defines a TonalUniverse that consists in an set of Tonalities, functions and relations among them. It can be used to analyze a chord relation to any tonality +Defines a TonalUniverse that consists in an set of Tonalities, functions and relations among them. It can be used to analyze a chord relation to any major and minor tonality. Part of link::Guides/superharmony::, a library with utilities for tonal analysis of chords. @@ -24,7 +24,7 @@ subsection:: Accessing METHOD:: getHarmonyList -From a string of roman numeral functions, returns a proposal of chords with those tonal functions. +Parses a string with tonality and harmonies information in roman notation and, returns a list harmonies/chords with those tonal functions. code:: ( u=TonalUniverse(); @@ -41,12 +41,91 @@ C,m: V7/V V7 I :: ARGUMENT:: -String with current tonality and harmonies in roman numerals separeted by space. +String with current tonality and harmonies in roman numerals separeted by space. Each line represents a tonality, the base and type are defined at the begining. After the colon the Roman numbers are added separated by space, it can have seventh or secondary functions. +code:: +"BASE_NOTE,TYPE_SCALE: ROMAN_NUMBER" +:: + +RETURNS:: +List of link::Classes/Harmony:: with those tonal functions. + + +METHOD:: degreeSimple +Returns the roman degree of the input Harmony with respect to the passed tonality +code:: +u=TonalUniverse(); +c = Tonality(0,"M") +u.degreeSimple(Harmony([0,4,7]), c) // 1 +u.degreeSimple(Harmony([9,12,16]), c) // 6 +u.degreeSimple(Harmony.create(5,"M"), c) // 4 +:: + +ARGUMENT:: +link::Classes/Harmony:: to check. + +ARGUMENT:: +link::Classes/Tonality:: Tonality as reference. + +RETURNS:: +Integer value with degree of note (1-7) if harmony is part of the Tonality, 0 if its not part. + + +METHOD:: degreeSimpleCurrent +Returns the roman degree of the input Harmony with respect to current selected tonality in the tonality universe. +code:: +u=TonalUniverse() +u.setCurrentScale(9,"M"); + +u.degreeSimpleCurrent(Harmony([0,4,7])) // 0 +u.degreeSimpleCurrent(Harmony([9,13,16])) // 1 +u.degreeSimpleCurrent(Harmony.create(1,"m")) // 3 +:: + +ARGUMENT:: +link::Classes/Harmony:: to check. RETURNS:: -List of Harmonies with those tonal functions. +Integer value with degree of note (1-7) if harmony is part of the Tonality, 0 if its not part. +METHOD:: degreeSecondary +Finds the degrees to which the input harmony has a secondary function in the passed tonality, for example a secondary dominant or any other combination like V/II III/VI, etc. +code:: +u=TonalUniverse(); +c = Tonality(0,"M") +u.degreeSecondary(Harmony([0,4,7]), c).print // scale 1 M degree: 1 label- +u.degreeSecondary(Harmony([9,12,16]), c).print // scale 1 M degree: 6 label +u.degreeSecondary(Harmony.create(2,"D7"), c).print // scale 5 M degree: 5 label +:: + +ARGUMENT:: +link::Classes/Harmony:: to check. + +ARGUMENT:: +link::Classes/Tonality:: Tonality as reference. + +RETURNS:: +link::Classes/TonalCoordinate:: with the information for the secondary function of the harmony with respect to the tonality. + + + + +METHOD:: getVectorPercentages +Finds the percentage, value between 0 and 1 of the notes that belong to each tonality 12 mayor and 12 minor. +code:: +u=TonalUniverse(); +c = Tonality(0,"M") +u.getVectorPercentages([0,4,7]) +// -> [ 1.0, 0.33333333333333, 0.66666666666667, 0.66666666666667, 0.33333333333333, 1.0, 0.0, 1.0, 0.66666666666667, 0.33333333333333, 0.66666666666667, 0.33333333333333, 0.66666666666667, 0.66666666666667, 0.66666666666667, 0.0, 1.0, 1.0, 0.0, 0.66666666666667, 0.66666666666667, 0.66666666666667, 0.33333333333333, 0.66666666666667 ] + +:: + +ARGUMENT:: +List of notes, interger values + + +RETURNS:: +Array of 24 values with percentage of notes that belong to each tonality, first 12 values are 12 mayor tonalities, next 12 values are the 12 minor tonalities starting with C. section:: Authors diff --git a/HelpSource/Guides/graph.png b/HelpSource/Guides/graph.png new file mode 100644 index 0000000..0c00f69 Binary files /dev/null and b/HelpSource/Guides/graph.png differ diff --git a/HelpSource/Guides/superharmony.schelp b/HelpSource/Guides/superharmony.schelp index 4a5cb3e..af40e00 100644 --- a/HelpSource/Guides/superharmony.schelp +++ b/HelpSource/Guides/superharmony.schelp @@ -2,17 +2,104 @@ title:: Superharmony summary:: Harmony universe utilities categories:: Libraries>superharmony -Superharmony is a diverse library of utilities for exploring tonality. +Superharmony is a library of utilities for exploring tonality. It containes classes for defining a link::Classes/Harmony::, link::Classes/Tonality::, link::Classes/TonalUniverse:: as a set of notes and functions between them. section:: Components subsection:: Harmony +You can create and manipulate harmonies as a set of notes and functions. For example: + +code:: +a = Harmony.new([0,4,7]) +b = Harmony([0,4,7]) +// C minor chord [0,3,7,12] +a = Harmony.create(0,"m") + +// A major chord [9,13,16,21] +b = Harmony.create(9,"M") + +a= Harmony([0,4,7,11]) // CM7 +a.print +// Fundamental: C M7 7 +// Notes: [ 0, 4, 7, 11 ] +// Simplified Notes[ 0, 4, 7, 11 ] +// Interval types[ 1, 3, 5, 7 ] +:: + + subsection:: Tonality +We can create a tonality object that will give information about harmonies in it and their tonal functions. For example: + +code:: +a = Tonality.new(0,"M") +b = Tonality(0,"m") + +Tonality.degreeRoman2Number("I") // 0 +Tonality.degreeRoman2Number("iii") // 2 +Tonality.degreeRoman2Number("VII") // 6 + + +// Get Closest chord +a= Harmony([0,4,7,12]) +b= Harmony.create(9,"D7") +b.print + +c=Tonality.getClosestChord(a,b) +c.print +// [9,13,16,19] + +// Get notes percentages that belong to a tonality. + +a = Tonality(0,"M") // [0,2,4,5,7,9,11] +a.notesPercentage([0,2,4]) // 1.0 +a.notesPercentage([1,3,6]) // 0.0 +a.notesPercentage([4,6,7]) // 0.666... +a.notesPercentage([0,1]) // 0.5 + +// Get Harmony from degree +a = Tonality(0,"M") // [0,2,4,5,7,9,11] +h = a.getHarmonyfromDegree("I") // Harmony +h.printSimple // CM +a.getHarmonyfromDegree("i").printSimple // CM since its case insensitive +a.getHarmonyfromDegree("II").printSimple // Dm +a.getHarmonyfromDegree("III").printSimple // Em +:: + + + subsection:: TonalUniverse +With tonal universe you can get information about what chord belongs to what tonality and create sequences of chords from a string of roman degree numbers: + +In this string, each line represents a tonality and FUNDAMENTAL,MAJOR/MINOR, separeted by a colon. After this a sequence of roman numerals are added, and you can add secondary functions like the fifht degree of the sixt V7/VI. When passed to the "getHarmonyList" function, this is parsed and we return an array of chords that we can pass a view bean + +code:: +( +u=TonalUniverse(); +~str= +"C,m: I V7/VI VI V VI II II7 IV VII7 I +E,m: V7 I IV V7/V I +C,m: V7/V V7 I +"; +// This function takes a while and logs the progress in the console. +~chords=u.getHarmonyList(~str); +~arrayNotes=~chords.collect({arg ar; ar.notesHarmony[0..3]}); +) +// -> [ [ 0, 3, 7, 12 ], [ -2, 3, 7, 13 ], [ -4, 3, 8, 12 ], [ -5, 2, 7, 11 ], [ -4, 3, 8, 12 ], [ -4, 5, 8, 14 ], [ -7, 2, 8, 12 ], [ -7, 0, 8, 12 ], [ -7, -1, 8, 14 ], [ -9, 0, 7, 15 ], [ -9, -1, 9, 18 ], [ -8, -1, 7, 19 ], [ -8, 0, 9, 21 ], [ -8, 1, 6, 22 ], [ -8, -1, 7, 23 ], [ -10, -3, 6, 24 ], [ -10, -5, 5, 23 ], [ -9, -5, 3, 24 ] ] +( +Pbind( + \note, Pseq(~arrayNotes.flat,1), + \dur, 0.2 +).play +) +~arrayNotes.flat.plot("Sequence", discrete:true) +:: + +image::graph.png:: section:: Author Cristian Banuelos, -dr_holomorfo \ No newline at end of file +dr_holomorfo + diff --git a/README.md b/README.md index ad928f6..7c0c596 100644 --- a/README.md +++ b/README.md @@ -1,214 +1,104 @@ -# superharmony -SuperCollider harmony helper utility. +# Superharmony -## Description -SuperCollider classes for creating chords and harmonies. +Superharmony is a [SuperCollider](https://supercollider.github.io/) library of utilities for exploring tonality. It containes classes for defining a Harmony, Tonality, TonalUniverse as a set of notes and functions between them. -- You can create chords -``` -// Example 1 -( -a=Harmony(); -a=a.create(5,"D7" ); -a.nameHarmonyString.postln; -a.notesHarmony.postln; -a.harmonyTypeStr.postln; -) -``` -- You can create chord progressions with tonal information and modulation. -``` -//Example 2 -u=TonalUniverse(); -~str= -"C,m: I V7/VI VI V VI II II7 IV VII7 I -E,m: V7 I IV V7/V I -C,m: V7/V V7 I -"; -~chords=u.getHarmonyList(~str); -~arrayNotes=~chords.collect({arg ar; ar.notesHarmony[0..3]}); -``` +## Components +###Harmony -## Installation -Add the main folde to the Super Collider extensions folder. - - - -TITLE:: Harmony -summary:: Representation of a chord with its harmonic content. -categories:: Chords, Harmonies, Tonalities - - -DESCRIPTION:: -Defines a chord as an array of numbers toghether with its harmonic content, including its chord type, base and inversion. - -Part of link::Guides/superharmony::, a library with utilities for tonal analysis of chords. - -CLASSMETHODS:: - -METHOD:: new -Creates a new Harmony instance, it takes an array of integer numbers. Can be called with the shorthand notation -code:: +You can create and manipulate harmonies as a set of notes and functions. For example: +``` a = Harmony.new([0,4,7]) b = Harmony([0,4,7]) -:: - -METHOD:: create -Creates a four voice harmony instance from the fundamental note and chord type from the list in link::Classes/ChordsDefinition:: where you can select triads, sevenths and ninth chords among others. For example -code:: // C minor chord [0,3,7,12] a = Harmony.create(0,"m") - +​ // A major chord [9,13,16,21] b = Harmony.create(9,"M") - -// G diminished seventh chord [7,10,13,16] -c = Harmony.create(7,"o7") - -// D dominant seventh [2,6,9,12] -d = Harmony.create(2,"D7") - -// B major ninth with fourth suspended [11,13,16,18,22] -e = Harmony.create(11,"M9sus4") -:: - -ARGUMENT:: -Fundamental note of the chord as an integer number. - -ARGUMENT:: -Type of chord, see link::Classes/ChordsDefinition:: for available types. - -INSTANCEMETHODS:: - -subsection:: Accessing - - -METHOD:: equivalent -Checks if two chords have the same chord and type, regardless of number of voices and order or octave. -code:: -a= Harmony([4,7,12,0]) -b= Harmony.create(12,"M") -c= Harmony([0,4,7]) -d= Harmony([0,3,7]) -a.equivalent(b) // true -a.equivalent(c) // true -a.equivalent(d) // false -:: - -METHOD:: fundamental -Fundamental interger value of a chord. -code:: -a= Harmony([0,4,9]) // A minor chord -a.fundamental // 9, which is the A value of the A minor chord -:: - -METHOD:: fundamentalString -Fundamental string value of a chord. -code:: -a= Harmony([0,4,9]) // A minor chord -a.fundamentalString // "A" -:: - -METHOD:: harmonyTypeStr -String value of the harmony type -code:: -a= Harmony([0,4,9]) // A minor chord -a.harmonyTypeStr // "m", which is the kinf of chord of A minor -:: - -METHOD:: inversion -Numerical value of the inversion of the chord, CM in root value would be [0,4,7] would have value 0, first inversion [4,7,12] would have value 1, and so on. -code:: -a= Harmony([0,4,7]) // A minor chord -a.inversion // "0", root position of C Major chord -a= Harmony([4,7,12]) // A minor chord -a.inversion // "1", first inversion oc C Major chord -a= Harmony([7,12,12+4]) // A minor chord -a.inversion // "2", first inversion oc C Major chord -:: - -METHOD:: inversionStr -String value of the inversion of the chord, CM in root value would be [0,4,7,11] would have value "7" as a seventh chord in root position, first inversion [4,7,12] would have value "6,5". Other inversions would have "6,4", "4,3", "2". This method works for triads and seventh chords. -code:: -a= Harmony([0,4,7,11,12]) -a.inversionStr // "7", root position of C M7 chord -b= Harmony([7,4,11,12,7+12]) -b.inversionStr // "6,5", first inversion of C M7 chord -c= Harmony([7,11,12,12+4]) -c.inversionStr // "4,3", second inversion of C M7 chord -:: - -METHOD:: notesHarmony -Array with the sorted notes in the harmony. -code:: -b= Harmony([7,4,12,19,11,4]) -b.notesHarmony // [ 4, 4, 7, 11, 12, 19 ] -:: - -METHOD:: notesSimplified -Array with simplified version of the array of notes. Notes are converted to pitch class module 12, duplicates are removed and elements are sorted ascending. -code:: -b= Harmony([7,4,12,11,4,19]) -b.notesSimplified // [ 0,4,7,11 ] -:: - -METHOD:: nameHarmonyNoInversionStr -String with fundamental letter value an type of chord string value -code:: -b= Harmony([7,4,12,11,4,19]) -b.nameHarmonyNoInversionStr // CM7 -:: - -METHOD:: nameHarmonyString -String with fundamental letter value an type of chord string value with inversion string added. -code:: -b= Harmony([7,4,12,11,4,19]) -b.nameHarmonyString // CM7 6,5 -:: - -METHOD:: notesInterval -Degree of each chord with respect to chord type, for example for C Major seventh chord [0,4,7,11], 0 would be the fundamental 1, 4 would be the and interval of third, 7 an interval of fifth and 11 the seventh interval. -code:: -a= Harmony([0,4,7,11]) // CM7 -a.notesInterval // [1,3,5,7] - -b= Harmony([7,4,12,11,4,19]) // CM7 -b.notesInterval // [ 3, 3, 5, 7, 1, 5 ] -:: - -METHOD:: print -Prints information about the harmony: Fundamental string, type, inversion, notes, simplified notes and interval types -code:: +​ a= Harmony([0,4,7,11]) // CM7 a.print // Fundamental: C M7 7 // Notes: [ 0, 4, 7, 11 ] // Simplified Notes[ 0, 4, 7, 11 ] // Interval types[ 1, 3, 5, 7 ] -:: +``` -METHOD:: printSimple -Prints simplifiedinformation about the harmony: Fundamental string, type and inversion. -code:: -a= Harmony([0,4,7,11]) // CM7 -a.printSimple // CM7 7 -:: +### Tonality +We can create a tonality object that will give information about harmonies in it and their tonal functions. For example: +``` +a = Tonality.new(0,"M") +b = Tonality(0,"m") +​ +Tonality.degreeRoman2Number("I") // 0 +Tonality.degreeRoman2Number("iii") // 2 +Tonality.degreeRoman2Number("VII") // 6 +​ +​ +// Get Closest chord +a= Harmony([0,4,7,12]) +b= Harmony.create(9,"D7") +b.print +​ +c=Tonality.getClosestChord(a,b) +c.print +// [9,13,16,19] +​ +// Get notes percentages that belong to a tonality. +​ +a = Tonality(0,"M") // [0,2,4,5,7,9,11] +a.notesPercentage([0,2,4]) // 1.0 +a.notesPercentage([1,3,6]) // 0.0 +a.notesPercentage([4,6,7]) // 0.666... +a.notesPercentage([0,1]) // 0.5 +​ +// Get Harmony from degree +a = Tonality(0,"M") // [0,2,4,5,7,9,11] +h = a.getHarmonyfromDegree("I") // Harmony +h.printSimple // CM +a.getHarmonyfromDegree("i").printSimple // CM since its case insensitive +a.getHarmonyfromDegree("II").printSimple // Dm +a.getHarmonyfromDegree("III").printSimple // Em +``` -EXAMPLES:: +### Tonal Universe +With tonal universe you can get information about what chord belongs to what tonality and create sequences of chords from a string of roman degree numbers: -Creating a chord -code:: -a = Harmony([0,4,7,10]) -a.print -// Fundamental: C D7 7 -// Notes: [ 0, 4, 7, 10 ] -// Simplified Notes[ 0, 4, 7, 10 ] -// Interval types[ 1, 3, 5, 7 ] -:: +In this string, each line represents a tonality and FUNDAMENTAL,MAJOR/MINOR, separeted by a colon. After this a sequence of roman numerals are added, and you can add secondary functions like the fifht degree of the sixt V7/VI. When passed to the "getHarmonyList" function, this is parsed and we return an array of chords that we can pass a view bean +``` +( +u=TonalUniverse(); +~str= +"C,m: I V7/VI VI V VI II II7 IV VII7 I +E,m: V7 I IV V7/V I +C,m: V7/V V7 I +"; +// This function takes a while and logs the progress in the console. +~chords=u.getHarmonyList(~str); +~arrayNotes=~chords.collect({arg ar; ar.notesHarmony[0..3]}); +) +// -> [ [ 0, 3, 7, 12 ], [ -2, 3, 7, 13 ], [ -4, 3, 8, 12 ], [ -5, 2, 7, 11 ], [ -4, 3, 8, 12 ], [ -4, 5, 8, 14 ], [ -7, 2, 8, 12 ], [ -7, 0, 8, 12 ], [ -7, -1, 8, 14 ], [ -9, 0, 7, 15 ], [ -9, -1, 9, 18 ], [ -8, -1, 7, 19 ], [ -8, 0, 9, 21 ], [ -8, 1, 6, 22 ], [ -8, -1, 7, 23 ], [ -10, -3, 6, 24 ], [ -10, -5, 5, 23 ], [ -9, -5, 3, 24 ] ] +( +Pbind( + \note, Pseq(~arrayNotes.flat,1), + \dur, 0.2 +).play +) +~arrayNotes.flat.plot("Sequence", discrete:true) + +``` +![Piano roll](./graph.png) + + + +## Installation +- Add the main folder to the Super Collider extensions folder. +- This libarary can also be installed as a quark by following the instructions in this link: [QUARKS TUTORIAL](https://doc.sccode.org/Guides/UsingQuarks.html) -section:: Authors -Cristian Banuelos, 2022. +### Author +Cristian Banuelos, dr_holomorfo +[wwww.holomorfo.com](https://www.holomorfo.com) diff --git a/classes/TonalCoordinate.sc b/classes/TonalCoordinate.sc index d357f3f..ae54956 100644 --- a/classes/TonalCoordinate.sc +++ b/classes/TonalCoordinate.sc @@ -22,6 +22,7 @@ TonalCoordinate{ " degree: ".post; degree.post; " label".post; - label.post; + label.postln; } } + \ No newline at end of file diff --git a/classes/TonalUniverse.sc b/classes/TonalUniverse.sc index 1fa2452..070bafc 100644 --- a/classes/TonalUniverse.sc +++ b/classes/TonalUniverse.sc @@ -135,19 +135,19 @@ TonalUniverse{ ^listaFinal; } - getVectorPercentages{arg listaArm; + getVectorPercentages{arg notesList; percentagesVector=Array.new(32); majorPercentage=Array.new(32); minorPercentage=Array.new(32); for(0,12-1,{arg i; var porc= - majorUniverse[i].notesPercentage(listaArm); + majorUniverse[i].notesPercentage(notesList); percentagesVector.add(porc); majorPercentage.add(porc); }); for(0,12-1,{arg i; var porc= - minorUniverse[i].notesPercentage(listaArm); + minorUniverse[i].notesPercentage(notesList); percentagesVector.add(porc); majorPercentage.add(porc); }); diff --git a/graph.png b/graph.png new file mode 100644 index 0000000..0c00f69 Binary files /dev/null and b/graph.png differ