Giter Site home page Giter Site logo

regorxxx / camelot-wheel-notation Goto Github PK

View Code? Open in Web Editor NEW
32.0 5.0 0.0 127 KB

Javascript implementation of the Camelot Wheel, ready to use "harmonic mixing" rules and translations for standard key notations. The wheel is a representation where musical keys are displayed as ‘hours’ on a clock followed by a letter (A, B). Its main use is mixing songs following a set of rules named "harmonic mixing" or "mixing in key".

License: GNU Affero General Public License v3.0

JavaScript 100.00%
javascript camelot-wheel in-key-mixing harmonic-mixing musical-keys open-key open-keys

camelot-wheel-notation's Introduction

Camelot-Wheel-Notation

version CodeFactor Codacy Badge GitHub
Javascript implementation of the Camelot Wheel, ready to use "harmonic mixing" rules and translations for Standard Key and Open Key notations. The Camelot Wheel is a representation where musical keys are displayed as ‘hours’ on a clock followed by a letter (A, B). Its main use is mixing songs following a set of rules named "harmonic mixing" or "mixing in key".

Usage

Working with keys

Lets say you have a currently working code to retrieve a list of keys from some files then, to translate Standard Keys like ('G#m' or 'Abm') into the Camelot Wheel Notation, you would do:

let objKey = camelotWheel.getKeyNotationObjectCamelot('Abm'); // {hour: 1, letter: 'A'} 
let objKeyOpen = camelotWheel.getKeyNotationObjectOpen('Abm'); // {hour: 6, letter: 'm'}

Can also translate back such object into Standard notation. Although note there are 2 ways to represent the same key, that is: Sharp and Flat. Both are equivalent.

... // where objKey = {hour: 1	, letter: 'A'}
let flatKey = camelotWheel.getKeyNotationFlat(objKey); // 'Abm'
let sharpKey = camelotWheel.getKeyNotationSharp(objKey); // 'G#m'

To simply test if the keys exist in the wheel (i.e. are valid):

camelotWheel.hasKey('G#m') // True
camelotWheel.hasKey('11A') // True
camelotWheel.hasKey('11C') // False
camelotWheel.hasKey(objKey) // True. Note objKey = {hour: 1, letter: 'A'} -> '1A'

Finally key objects may be translated from Camelot notation to Open Key notation and vice-versa.

// '{hour: 1, letter: 'A'} -> {hour: 6, letter: 'm'}'
objKeyOpen = camelotWheel.translateObjectCamelotToOpen(objKey);

Harmonic mixing

Once you got your keys translated into something usable within the wheel (objects), you can find harmonically compatible keys using the built-in methods:

  1. Perfect Match (nX -> nX): staying in the same 'hour' and letter.
  2. Energy Changes:
    • Energy Boost (nX -> n+1X): adding one 'hour' (+1), equivalent to going up a fifth.
    • Energy Drop (nX -> n-1X): subtracting one 'hour' (-1), equivalent to going down a fifth.
    • Energy Switch (nA -> nB): staying in he same 'hour' but changing the letter, equivalent to going from relative minor to major (and viceversa).
  3. Mood Changes:
    • Mood Boost (nA -> n+3B): adding three 'hours' (+3), equivalent to going from minor to major.
    • Mood Drop (nX -> n-3B): subtracting three 'hours' (-3), equivalent to going from major to minor.
  4. Key Changes:
    • Dominant Key (nA -> n+1B): subtracting one 'hour' (+1) and changing the letter.
    • Sub Dominant Key (nB -> n-1A): subtracting one 'hour' (+1) and changing the letter.
  5. Experimental Energy Changes:
    • Energy Boost ++ (nX -> n+2X): adding two 'hours' (+2), equivalent to going up a step.
    • Dramatic Energy Raise (nX -> n+7X): adding seven 'hours' (+7), equivalent to going up a half step.

Which are named: perfectMatch, energyBoost, energyDrop, energySwitch, moodBoost, moodDrop, domKey, subDomKey, energyRaise

For ex. to find the next key with an energy boost:

let objKey = camelotWheel.getKeyNotationObjectCamelot('Abm'); // {hour: 1, letter: 'A'}
let nextObjKey = camelotWheel.energyBoost(objKey); // {hour: 2	, letter: 'A'}

The same for a mood boost:

//  Note it works the same on both camelot and open key objects
let objKey = camelotWheel.getKeyNotationObjectOpen('C#m'); // {hour: 5, letter: 'm'}
let nextObjKey = camelotWheel.moodBoost(objKey); // {hour: 8, letter: 'm'}

While summing and subtracting is a pretty easy operation, note the hour it's a cyclic value from 1 to 12, therefore using the built-in methods is much easier than working manually with the objects. Also, it allows to easily create patterns to call the methods on successive movements:

...
const playlistLength = 50;
const movements = {
	perfectMatch: 	35	, // perfectMatch (=)
	energyBoost : 	10	, // energyBoost (+1)
	energyDrop  :	10	, // energyDrop (-1)
	energySwitch:	10	, // energySwitch (B/A)
	moodBoost   :	5	, // moodBoost (+3)
	moodDrop    :	5	, // moodDrop (-3)
	energyRaise :	5	, // energyRaise (+7)
	domKey      :	10	, // domKey (+1 & B/A) = energyBoost & energySwitch
	subDomKey   :	10	, // subDomKey (-1 & B/A) = energyDrop & energySwitch
}; // Sum must be 100%
let pattern = [];
Object.keys(movements).forEach((key) => {
	pattern = pattern.concat(
		Array(Math.ceil(playlistLength * movements[key] / 100)
	).fill(key));
});
// Sort randomly
let last = pattern.length;
let n;
while (last > 0) {
	n = Math.floor(Math.random() * last);
	--last;
	[pattern[n], pattern[last]] = [pattern[last], pattern[n]];
}
// And apply to your tracks
for (let i = 0; i < playlistLength; i++) {
  keyCurrent = yourOwnTagFunc();
  camelotKeyCurrent = camelotWheel.getKeyNotationObject(keyCurrent);
  nextKeyObj = camelotKeyCurrent ? camelotWheel[pattern[i]](camelotKeyCurrent) : null;
  ...
 }

Alternatively, a pattern like that can be created with this method:

const playlistLength = 50;
const pattern = camelotWheel.createHarmonicMixingPattern(playlistLength);

... and applied directly to a key object to get the list of keys which would give such pattern:

...
let objKey = camelotWheel.getKeyNotationObjectOpen('C#m'); // {hour: 5, letter: 'm'}
// Works with both Camelot and Open Keys objects
const pattern = camelotWheel.applyPattern(objKey, pattern); // An array of key objects

Real World Implementation

As is, the Camelot Wheel only translates keys and outputs the next key when using one of the "harmonic mixing" rules. But to get it working with real files, you either need some library which reads tags from files or some implementation within a music player.
You can find such examples in these foobar2000's scripts:

  1. Search-by-Distance-SMP: creates playlists with similar tracks by multiple methods and following "harmonic mixing" rules.
  2. Playlist-Tools-SMP: takes an already existing playlist as pool and creates a new one following "harmonic mixing" rules.

harmonicmix

camelot-wheel-notation's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

camelot-wheel-notation's Issues

Possible demo?

Maybe it could be possible to set up some form of demo somewhere?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.