Skip to content

A music theory C++ library, originally based on ofxMusicTheory, originally based on the Python Mingus library

License

Notifications You must be signed in to change notification settings

VSTLab/NotofxMusicTheory

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ofxMusicTheory

image

This project was originally created as: A music theory openFrameworks addon originally based on the Python Mingus library

By Andreas Borg on 28/01/2013

crea.tion.to

Goal of this port

I wanted to see if I could use the lib for my music projects which are not related to openFrameworks.

I wanted to make it compile for Visual Studio 2022.

Now that I went through the code and tested it, I came to the conclusion that though the library does the job, the way it's designed does not really suit my needs and coding methods. I will not go further using it then. I'd rather develop a new one from scratch, and use this one as a reference if I need to.

Consequently, I will not maintain it in any way.

If you plan using it, you should fork and rewrite maintain the code as needed.

Changes made

Changes made in april 2024:

Remove openFrameworks dependencies to make a simple C++ library and a Windows test console command. Make the project compile under Visual Studio 2022 and test.

Replace openFrameworks libraries used by:

  • boost 1.84
  • mathfu
  • spdlog (in fact, I just reference spdlog in include path but not use it. I just put traces logs in #ifdef LOGS directive)

Install and compile

Install dependencies:

  • boost 1.84
  • mathfu
  • spdlog (in fact, I just reference spdlog in include path but not use it. I just put traces logs in #ifdef LOGS directive, so, this one is not needed)

The best is to install them in a common directory.

Example:

C:\ExtLibs
C:\ExtLibs\boost_1_84_0
C:\ExtLibs\mathfu
C:\ExtLibs\spdlog

Clone the repository

Config the solution

If you followed the directory structure mentioned above, edit config\common.props to set the path to ExtLibs. It should compile and run. Otherwise, edit each config\*.props file to set the correct path to libs.

Open the solution in VS 2022 Press run. It should compile and run the test console application.

Usage

Add the SolutionPath\MusicTheory\include to you Include Path

#include <MusicTheory/MusicTheory.h> 

where you want to use it

Example code


    NotePtr C = Note::create("C");
    cout<<C<<endl;
    
    NotePtr C2 = Note::fromInt(60);
    cout<<C2<<endl;
    
    C2->transpose(7);
    cout<<C2<<endl;
    
    NotePtr b = C->getAugmented();
    
    C->augment();
    cout<<"Aug "<<C<<endl;
    
    C->diminish();
    cout<<"Dim "<<C<<endl;
    
    C->diminish();
    cout<<"Dim "<<C<<endl;
    
    
    b->changeOctave(-1);
    b->augment();
    b->augment();
    b->augment();
    cout<<b<<endl;
    
    
    cout<<"Diatonic name: "<<b->getDiatonicName()<<endl;
    
    NotePtr c = b->getOctaveDown();
    cout<<"Oct down: "<<c<<endl;
    
    NotePtr r = Note::create("C");
   
    cout<<"Get diatones of: "<<r<<endl;
    
    deque<NotePtr> scale = Diatonic::getNotes(r);
     
    for(int i=0;i<scale.size();i++){
        cout<<scale[i]<<endl;
    }

    
    NotePtr root = Note::create("C");
    
    
    NotePtr abs6 = Interval::sixth(root,root);
    cout<<"Absolute sixth of "<<root<<" is "<<abs6<<endl;
    
    
    
    NotePtr abs4 = Interval::sixth(root,root);
    
        
    NotePtr m2 = Interval::minorSecond(root);
    cout<<"Min second of "<<root<<" is "<<m2<<endl;
    
    NotePtr M2 = Interval::majorSecond(root);
    cout<<"Maj second of "<<root<<" is "<<M2<<endl;
    
    
    NotePtr m3 = Interval::minorThird(root);
    cout<<"Min third of "<<root<<" is "<<m3<<endl;
    
    NotePtr M3 = Interval::majorThird(root);
    cout<<"Maj third of "<<root<<" is "<<M3<<endl;
    
    
    NotePtr m4 = Interval::minorFourth(root);
    cout<<"Min fourth of "<<root<<" is "<<m4<<endl;
    
    NotePtr P4 = Interval::perfectFourth(root);
    cout<<"Perfect fourth of "<<root<<" is "<<P4<<endl;
    
    NotePtr M4 = Interval::majorFourth(root);
    cout<<"Maj fourth of "<<root<<" is "<<M4<<endl;
    
    
    NotePtr m5 = Interval::minorFifth(root);
    cout<<"Min fifth of "<<root<<" is "<<m5<<endl;
    
    NotePtr P5 = Interval::perfectFifth(root);
    cout<<"Perfect fifth of "<<root<<" is "<<P5<<endl;
    
    NotePtr m6 = Interval::minorSixth(root);
    cout<<"Min sixth of "<<root<<" is "<<m6<<endl;
    
    NotePtr M6 = Interval::majorSixth(root);
    cout<<"Maj sixth of "<<root<<" is "<<M6<<endl;
    
    NotePtr m7 = Interval::minorSeventh(root);
    cout<<"Min seven of "<<root<<" is "<<m7<<endl;

    NotePtr M7 = Interval::majorSeventh(root);
    cout<<"Maj seven of "<<root<<" is "<<M7<<endl;
    
   
    
    string m = Chord::getFullName("mM7");
    
    cout<<Chord::getFullName("mM7")<<" This one not found:" <<Chord::getFullName("oddname")<<endl;
  
    
    ChordPtr ch = Chord::halfDiminishedSeventh(root);
    cout<<ch<<endl;;
    
    
    ChordPtr st = Chord::tonic7(root);
    cout<<"Subtonic to "<<root<<" is "<<st<<endl;
    
    
    ChordPtr subdom = Chord::subdominant(root);
    cout<<"Subdominant to "<<root<<" is "<<subdom<<endl;
    
    
    ChordPtr subdomInv = Chord::firstInversion(subdom);
    cout<<"Subdominant first inversion is "<<subdomInv<<endl;
    
    
    /*
     Extended fifth chords are made of built of 5 notes at third dist
     */
    
    ChordPtr ext5 = Chord::majorNinth(root);
    cout<<"Ext fifth eg."<<ext5<<endl;
    
    

    bool useShorthand = true;
    bool allowInvensions = true;
    bool allowPolychords = true;
    
    deque<NotePtr> triad = {
        {Note::create("F")},
        {Note::create("G")},
        {Note::create("C")}
    };
    
    cout<<"Triad analysis "<<endl;
    Chord::print(triad);
    vector<string> analyse = Chord::analyse(triad, useShorthand,allowInvensions,allowPolychords);
    for(int i = 0;i<analyse.size();i++){
        cout<<"Opt "<<i<<": "<<analyse[i]<<endl;
    }
    
    
    
    deque<NotePtr> seventh = {
        {Note::create("C")},
        {Note::create("E")},
        {Note::create("G")},
        {Note::create("A")}
    };
    
    cout<<endl<<"Seventh analysis "<<endl;
    
    Chord::print(seventh);
    
    analyse = Chord::analyse(seventh, useShorthand,allowInvensions,allowPolychords);
    for(int i = 0;i<analyse.size();i++){
        cout<<"Opt "<<i<<": "<<analyse[i]<<endl;
    }
    
    
    deque<NotePtr> ext = {
        {Note::create("C")},
        {Note::create("E")},
        {Note::create("G")},
        {Note::create("B")},
        {Note::create("D")}
    };

    cout<<endl<<"Extended  fifth analysis "<<endl;
    Chord::print(ext);
    analyse = Chord::analyse(ext, useShorthand,allowInvensions,allowPolychords);
    for(int i = 0;i<analyse.size();i++){
        cout<<"Opt "<<i<<": "<<analyse[i]<<endl;
    }
    
    
    cout<<endl<<"Extended  sixth analysis "<<endl;
    ext.push_back(Note::create("A"));
    Chord::print(ext);
    analyse = Chord::analyse(ext, useShorthand,allowInvensions,allowPolychords);
    for(int i = 0;i<analyse.size();i++){
        cout<<"Opt "<<i<<": "<<analyse[i]<<endl;
    }
    
    

    
    
    cout<<endl<<"Extended  seventh analysis "<<endl;
    
    ChordPtr ext7 = Chord::majorNinth(root);
    
    //add 11 and 13 to the 9th
    ext7->notes.push_back(Interval::fourth(root, root));
    ext7->notes.push_back(Interval::sixth(root, root));
    
    //cout<<"Ext seventh eg."<<ext7<<endl;
    
    //turn vector into deque...(using deque since internally we need to shuffle aruond to test different inversions
    deque<NotePtr> ch13;
    ch13.insert(ch13.begin(),ext7->notes.begin(),ext7->notes.end());
    
    Chord::print(ch13);
    
    analyse = Chord::analyse(ch13, useShorthand,allowInvensions,allowPolychords);
    for(int i = 0;i<analyse.size();i++){
        cout<<"Opt "<<i<<": "<<analyse[i]<<endl;
    }

    
    
    
    allowPolychords = true;
    
    
    cout<<endl<<"Polychord analysis"<<endl;
    
    deque<NotePtr> poly = Chord::triad(Note::create("C"),Note::create("C"))->notes;
    
    deque<NotePtr> chord2= Chord::minorTriad(Note::create("F#"))->notes;
    
    poly.insert(poly.end(), chord2.begin(),chord2.end());
    
    
    Chord::print(poly);
    
    analyse = Chord::analyse(poly, useShorthand,allowInvensions,allowPolychords);
    for(int i = 0;i<analyse.size();i++){
        cout<<"Opt "<<i<<": "<<analyse[i]<<endl;
    }

    
    cout<<endl<<"Scales"<<endl;
    ScalePtr lyd = Scale::getLydian(Note::create("F"));
    cout<<lyd<<endl;
    


    ScalePtr melMin = Scale::getMelodicMinor(Note::create("C"));
    cout<<melMin<<endl;
    
    ScalePtr pentaMaj = Scale::getPentatonicMajor(Note::create("C"));
    cout<<pentaMaj<<endl;
    
    
    ScalePtr hirajoshi = Scale::getHirajoshi(Note::create("C"));
    cout<<hirajoshi<<endl;
    
    
    ScalePtr mixo = Scale::getMixolydian(Note::create("C",3));
    cout<<mixo<<endl;
    
    ScalePtr prygian = Scale::getPhrygian(Note::create("C",3));
    cout<<prygian<<endl;

    
    ScalePtr flamenco = Scale::getFlamenco(Note::create("E",3));
    cout<<flamenco<<endl;
    
    ScalePtr Zen =  Scale::getInSen(Note::create("C",3));
    
    
    
    
    cout<<"Scales for 7b9b5"<<endl;
    vector<string>scales = Scale::getScalesForChord("7b9b5");
    Scale::print(scales);
    
    
    NotePtr nn  = Interval::fromShorthand(Note::create("C",4), "b3");
    cout<<nn<<endl;
    
    melMin = Scale::getScaleFromString(scales[0], Note::create("C",4));
    cout<<melMin<<endl;
    
    
    cout<<"Progressions"<<endl;
    
    
    
    
    cout<<"V7 to "<<root<<" is ";
    ChordPtr dom7= Progression::getChordFromRoman("V7",root);
    cout<<dom7<<endl;
    
    cout<<"VIdim7 to "<<root<<" is ";
  
    
    
    
    ChordPtr pchord = Progression::getChordfromChordFunction("VIdim7",root);//add dim etc
    cout<<pchord<<endl;
    
    
    string progStr = "bIIdim7,VM7";
    deque<ChordPtr> prog = Progression::fromString(progStr,root);
    
    cout<<progStr<<" where I is "<<root<<endl;
    Progression::print(prog);
    
    
    string subtituteMe = "IV7";
    cout<<endl<<"Harmonic substitution of "<<subtituteMe<<" ";
    Progression::print(Progression::substituteHarmonic(subtituteMe));
    
    
    subtituteMe = "VIm7";
    cout<<endl<<"Minor for major substitution of "<<subtituteMe<<" ";
    Progression::print(Progression::substituteMinorForMajor(subtituteMe));
    
    
    subtituteMe = "VM7";
    cout<<endl<<"Major for minor substitution of "<<subtituteMe<<" ";
    Progression::print(Progression::substituteMajorForMinor(subtituteMe));

    subtituteMe = "VII";
    cout<<endl<<"Dim for dim substitution of "<<subtituteMe<<" ";
    Progression::print(Progression::substituteDiminishedForDiminished(subtituteMe));

    
    subtituteMe = "VIIdim";
    cout<<endl<<"Dim for dom substitution of "<<subtituteMe<<" ";
    Progression::print(Progression::substituteDiminishedForDominant(subtituteMe));
    
    
  
    //NotePtr root("E",7);
    
    
    
    ChordPtr I = Progression::getChordfromChordFunction("I",root);
    cout<<I<<endl;
    
    ChordPtr II = Progression::getChordfromChordFunction("II",root);
    cout<<II<<endl;
    
    
    ChordPtr IV = Progression::getChordfromChordFunction("IVdim",root);
    cout<<IV<<endl;

    ChordPtr V7 = Progression::getChordfromChordFunction("V7",root);
    cout<<V7<<endl;
    

Output:

Note C-3 (C-60)
Note C-3 (C-60)
Note G-3 (G-67)
Aug Note C#-3 (C#-61)
Dim Note C-3 (C-60)
Dim Note B-2 (Cb-59)
Note E-2 (C####-52)
Diatonic name: E
Oct down: Note E-1 (C####-40)
Get diatones of: Note C-3 (C-60)
Note C-3 (C-60)
Note D-3 (D-62)
Note E-3 (E-64)
Note F-3 (F-65)
Note G-3 (G-67)
Note A-3 (A-69)
Note B-3 (B-71)
Absolute sixth of Note C-3 (C-60) is Note A-3 (A-69)
Min second of Note C-3 (C-60) is Note C#-3 (C#-61)
Maj second of Note C-3 (C-60) is Note D-3 (D-62)
Min third of Note C-3 (C-60) is Note D#-3 (D#-63)
Maj third of Note C-3 (C-60) is Note E-3 (E-64)
Min fourth of Note C-3 (C-60) is Note E-3 (E-64)
Perfect fourth of Note C-3 (C-60) is Note F-3 (F-65)
Maj fourth of Note C-3 (C-60) is Note F-3 (F-65)
Min fifth of Note C-3 (C-60) is Note F#-3 (F#-66)
Perfect fifth of Note C-3 (C-60) is Note G-3 (G-67)
Min sixth of Note C-3 (C-60) is Note G#-3 (G#-68)
Maj sixth of Note C-3 (C-60) is Note A-3 (A-69)
Min seven of Note C-3 (C-60) is Note A#-3 (A#-70)
Maj seven of Note C-3 (C-60) is Note B-3 (B-71)
 minor/major seventh This one not found:Chord not found
Chord Cm7b5 [ Note C-3 (C-60), Note D#-3 (D#-63), Note F#-3 (F#-66), Note A#-3 (A#-70) ]

Subtonic to Note C-3 (C-60) is Chord C7 [ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67), Note B-3 (B-71) ]

Subdominant to Note C-3 (C-60) is Chord F/C [ Note C-3 (C-60), Note F-3 (F-65), Note A-3 (A-69) ]

Subdominant first inversion is Chord F [ Note F-3 (F-65), Note A-3 (A-69), Note C-4 (C-72) ]

Ext fifth eg.Chord CM9 [ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67), Note B-3 (B-71), Note D-4 (D-74) ]

Triad analysis 
[ Note F-3 (F-65), Note G-3 (G-67), Note C-3 (C-60) ]
Opt 0: Fsus2
Opt 1: Csus4

Seventh analysis 
[ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67), Note A-3 (A-69) ]
Opt 0: CM6
Opt 1: Am7
Opt 2: Am7|CM

Extended  fifth analysis 
[ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67), Note B-3 (B-71), Note D-3 (D-62) ]
Opt 0: CM9
Opt 1: GM|CM
Opt 2: GM|CM7
Opt 3: Em7|CM
Opt 4: GM6|CM
Opt 5: Em7|CM7
Opt 6: GM6|CM7

Extended  sixth analysis 
[ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67), Note B-3 (B-71), Note D-3 (D-62), Note A-3 (A-69) ]
Opt 0: CM13
Opt 1: Am11
Opt 2: Bm7|CM
Opt 3: Bm7|CM7
Opt 4: Bm7|CM9
Opt 5: Em11|CM
Opt 6: G6/9|CM
Opt 7: Em11|CM7
Opt 8: G6/9|CM7
Opt 9: Em11|CM9
Opt 10: G6/9|CM9

Extended  seventh analysis 
[ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67), Note B-3 (B-71), Note D-4 (D-74), Note F-3 (F-65), Note A-3 (A-69) ]
Opt 0: CM13
Opt 1: G13
Opt 2: Dm13
Opt 3: Dm|CM
Opt 4: Dm|CM7
Opt 5: Dm|CM9
Opt 6: Dm|CM11
Opt 7: Bm7b5|CM
Opt 8: Dm6|CM
Opt 9: Bm7b5|CM7
Opt 10: Dm6|CM7
Opt 11: Bm7b5|CM9
Opt 12: Dm6|CM9
Opt 13: Bm7b5|CM11
Opt 14: Dm6|CM11
Opt 15: G9|CM
Opt 16: G9|CM7
Opt 17: G9|CM9
Opt 18: G9|CM11
Opt 19: G13|CM
Opt 20: G13|CM7
Opt 21: G13|CM9
Opt 22: G13|CM11

Polychord analysis
[ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67), Note F#-3 (F#-66), Note A-3 (A-69), Note C#-4 (C#-73) ]
Opt 0: F#m|CM
Opt 1: A13|CM

Scales
Scale F-3 lydian [ Note F-3 (F-65), Note G-3 (G-67), Note A-3 (A-69), Note B-3 (B-71), Note C-4 (C-72), Note D-4 (D-74), Note E-4 (E-76) ]

Scale C-3 melodicMinor [ Note C-3 (B#-60), Note D-3 (C##-62), Note D#-3 (D#-63), Note F-3 (E#-65), Note G-3 (F##-67), Note A-3 (G##-69), Note B-3 (A##-71) ]

Scale C-3 pentatonicMajor [ Note C-3 (C-60), Note D-3 (D-62), Note E-3 (E-64), Note G-3 (G-67), Note A-3 (A-69) ]

Scale C-3 hirajoshi [ Note C-3 (C-60), Note C#-3 (C#-61), Note F-3 (F-65), Note G-3 (G-67), Note G#-3 (G#-68) ]

Scale C-3 mixolydian [ Note C-3 (C-60), Note D-3 (D-62), Note E-3 (E-64), Note F-3 (F-65), Note G-3 (G-67), Note A-3 (A-69), Note Bb-3 (Bb-70) ]

Scale C-3 phrygian [ Note C-3 (B#-60), Note C#-3 (C#-61), Note D#-3 (D#-63), Note F-3 (E#-65), Note G-3 (F##-67), Note G#-3 (G#-68), Note A#-3 (A#-70) ]

Scale E-3 flamenco [ Note E-3 (E-64), Note F-3 (F-65), Note G-3 (G-67), Note G#-3 (G#-68), Note A-3 (A-69), Note B-3 (B-71), Note C-4 (C-72), Note D-4 (D-74) ]

Scales for 7b9b5
[ melodicMinorVII ]
Note D#-4 (D#-75)
Scale C-4 melodicMinorVII [ Note C-4 (B#-72), Note C#-4 (C#-73), Note D#-4 (D#-75), Note E-4 (E-76), Note F#-4 (F#-78), Note G#-4 (G#-80), Note A#-4 (A#-82) ]

Progressions
V7 to Note C-3 (C-60) is Chord G7/D [ Note D-3 (D-62), Note F-3 (F-65), Note G-3 (G-67), Note B-3 (B-71) ]

VIdim7 to Note C-3 (C-60) is Chord Adim7 [ Note A-3 (A-69), Note C-4 (C-72), Note D#-4 (D#-75), Note Gb-4 (Gb-78) ]

bIIdim7,VM7 where I is Note C-3 (C-60)
[ Chord C#dim7 [ Note C#-3 (C#-61), Note E-3 (E-64), Note G-3 (G-67), Note Bb-3 (Bb-70) ]
, Chord GM7 [ Note G-3 (G-67), Note B-3 (B-71), Note D-4 (D-74), Note F#-4 (F#-78) ]
 ]

Harmonic substitution of IV7 [ II7, VI7 ]

Minor for major substitution of VIm7 [ IM7 ]

Major for minor substitution of VM7 [ IIIm7 ]

Dim for dim substitution of VII [ IIdim, IVdim, bVIdim ]

Dim for dom substitution of VIIdim [ Vdom7, bVIIdom7, bIIdom7, IVdom7 ]
Chord C [ Note C-3 (C-60), Note E-3 (E-64), Note G-3 (G-67) ]

Chord D [ Note D-3 (D-62), Note F-3 (F-65), Note A-3 (A-69) ]

Chord Fdim [ Note F-3 (F-65), Note G#-3 (G#-68), Note B-3 (B-71) ]

Chord G7/D [ Note D-3 (D-62), Note F-3 (F-65), Note G-3 (G-67), Note B-3 (B-71) ]

About

A music theory C++ library, originally based on ofxMusicTheory, originally based on the Python Mingus library

Topics

Resources

License

Stars

Watchers

Forks

Languages

  • C++ 99.2%
  • C 0.8%