Code Monkey home page Code Monkey logo

mustemi's Introduction

Travis CI w/ Logo CodeCov codebeat badge Generic badge js-standard-style Known Vulnerabilities License: MIT

MUSTEMI - MUSic ThEory for MIdi applications

This package provides the means to produce Midi note numbers from either numeric degrees relative to a given scale, note names (eg 'C', 'Eb'), chord names (eg 'Cm7b5'), or Nashville numbers. There are examples for each of these given below, as well as a couple of examples of using this package with a midi controller and a DAW. This package can be used both in a node application and in the browser.

Installation

npm install mustemi

Basic Examples

These demonstrate how to use the package to produce MIDI note numbers from scale degrees.

import { core } from '../index.js' // you should use: from 'mustemi'

let result

// Set middle C octave.  By default this is 4, but your setup
// might require it to be 3
//core.setOrigin(3)

// Chromatic numbers of the major scale
result = core.scaleChromatics['Ionian']
console.log('ex 1:', result)
// <= [ 0, 2, 4, 5, 7, 9, 11 ]

// Chromatic numbers of the 3rd mode mode
result = core.scaleChromatics['Phrygian']
console.log('ex 2:', result)
// <= [ 0, 1, 3, 5, 7, 8, 10 ]

// Chromatics for a dominant 7th chord (relative to major scale),
// shifted (again by default) so that middle C is 60
result = core.chromatics([1, 3, 5, 'b7']) // relative scale is Ionian
console.log('ex 3:', result)
// <= [ 60, 64, 67, 70 ]

// Result is all 12 notes of  the western scale, starting at middle C
let degrees = ['1', '#1', '2', 'b3', '3', '4', '#4', '5', 'b6', '6', 'b7', '7']
result = core.chromatics(degrees, {scale: 'Ionian'})
console.log('ex 4:', result)
// <= [ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 ]

Chord Examples

In these examples, you'll see how to do the same for named chords.

import { chords } from '../index.js' // you should use: from 'mustemi'

let result

// This produces all 12 chromatics using note names rather than scale degrees
let notes = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
result = chords.notesToMidi(notes)
console.log('ex 1:', result)
// <= [ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 ]

// The default octave is 4, but you can specify other octaves for
// for individual notes, as in this example
result = chords.notesToMidi(['C:3', 'D#:2', 'E'])
console.log('ex 2:', result)
// <= [ 48, 39, 64 ]

// In addition, you can change the default octave
result = chords.notesToMidi(['C', 'D#:2', 'E:4'], {defaultOctave: 3})
console.log('ex 3:', result)
// <= [ 48, 39, 64 ]

// Here, we produce the midi notes for a C major 7th chord.
result = chords.chordToMidi({name: 'CM7'})
console.log('ex 4:', result)
// <= [ 60, 64, 67, 71 ]

// And here, an Db major chord, in the 5th octave
result = chords.chordToMidi({name: 'Db:5'})
console.log('ex 5:', result)
// <= [ 73, 77, 80 ]

// Most common chord types are supported.
result = Object.keys(chords.chordDegrees)
console.log('ex 6:', result)
// <= [ '7', '', 'M', 'Dom', 'm', '+', 'b5', 'dim', 'aug', 'sus4', 'sus2',
//      'M6', 'm6', 'Dom7', 'M7', 'm7', 'mM7', '+7', '+M7', 'dim7', '7b5',
//      'm7b5', 'add9' ]

// If you don't find the one you want, or just want to introduce a
// shorthand for a particular type of chord, just add it
// to the 'chordDegrees' object at runtime
chords.chordDegrees['M7/3rd'] = [-4, 1, 3, 5, 7]
result = chords.chordToMidi({name: 'CM7/3rd'})
console.log('ex 7:', result)
// <= [ 52, 60, 64, 67, 71 ]

Nashville Number System

These examples show how to produce MIDI note numbers from Nashville notation.

import { chords } from '../index.js' // you should use: from 'mustemi'

let result

// You can use the Nashville Number system to specify
// chords.  The defaults produce 7th chords in the key of C.
// This gets the midi notes for a CM7 chord in the 3rd octave
result = chords.nashvilleToMidi({name: 1})
console.log('ex 1:', result)
// <= [ 60, 64, 67, 71 ]

// Here's an example producing a C major triad in the 3rd octave
result = chords.nashvilleToMidi({name: '1:3', scale:'M'})
console.log('ex 2:', result)
// <= [ 48, 52, 55 ]

// This produces the notes for the 3 chord of the minor scale.
// It will be a 7th chord, and key is still C
result = chords.nashvilleToMidi({name: 3, scale:'m7'})
console.log('ex 3:', result)
// <= [ 64, 68, 71, 75 ]

// This produces the notes for the 3 chord of the harmonic minor scale.
// The Key is now D, and we're producing triads
result = chords.nashvilleToMidi({name: 3, scale:'hm', key: 'D'})
console.log('ex 4:', result)
// <= [ 66, 70, 74 ]

// You can also specify a chord type explicitly.  This will override
// the default for the scale in use
result = chords.nashvilleToMidi({name: '2^M7:3', scale:'m7'})
console.log('ex 5:', result)
// <= [ 50, 54, 57, 61 ]

MIDI examples

Here's a simple example of using the package to output MIDI for consumption by a DAW or some other MIDI-aware sound engine such as Kontakt Player. This uses a few basic midi utilities in the examples directory of this package. If you check out this repo so that you can run these MIDI examples, you'll need to install the 'midi' package. It's not listed as a devDependency in package.json, because travis-ci can't handle it (it requires a C code-build step). Also, your OS will need to have a way to open a virtual MIDI device. On the platform I'm using, Windows 10, this is made possible by using a 3rd-party tool such as the one I use: LoopMIDI

import midi from 'midi'
import * as mu from './midiutils.js'
import { core, chords } from '../index.js' // you should use: from 'mustemi'

// use this to see what port number you need to open
mu.showDevices()

// open the output port
const port = new midi.Output()
port.openPort(1)

let opts = {
  start: 0,
  interval: 200,
  duration: 150,
}

var nums, len = 0
nums = [60,62,64,65,67,69,71]
len = mu.play(port, nums, {...opts,
  text: "Ascending C major scale, Raw MIDI"}) 

nums = core.chromatics([8,7,6,5,4,3,2,1])
len = mu.play(port, nums, {...opts, start: len,
  text: "Descending Ionian (C major) scale, degrees"})

nums = core.chromatics([1,2,3,4,5,6,7,8,7,6,5,4,3,2,1], {scale: 'Dorian'})
len = mu.play(port, nums, {...opts, start: len + 200,
  text: "Dorian scale, degrees"})


opts = {
  start: 0,
  interval: 50,
  duration: 150
}

let names = ['CM7', 'Dm7', 'Em7', 'FM7', 'G7', 'Am7', 'Bm7b5', 'CM7:5']
for (const i in names) {
  const name = names[i]
  nums = chords.chordToMidi({name: name})
  len = mu.play(port, nums, {...opts, start: len + 200,
    text: name + ' chord'})
}

let root = 'D'
for (let i=1; i<=8; i++) {
  const name = (i===8)? '1:5': i
  nums = chords.nashvilleToMidi({name: name, root: root})
  len = mu.play(port, nums, {...opts, start: len + 200, 
    text: 'Nashville ' + name + ' chord, ' + root + ' scale'})
}

Simple MIDI chord arpeggiator

In this example, we take input from a MIDI keyboard, and output arpeggios rooted at the notes received from the keyboard.

import midi from 'midi'
import * as mu from './midiutils.js'
import { core, chords } from '../index.js' // you should use: from 'mustemi'

// my daw is Ableton, so middle C is in octave 3
core.setOrigin(3)

// use this to see what port number you need to open
mu.showDevices()

/*
 * Open the output port - on my windows box, this is a loopMIDI device.
 * In my daw, I place a midi instrument on a track, and then set the
 * track input to this loopMIDI device
 */
const port = new midi.Output()
port.openPort(1)

/*
 * Set up to read midi note-on messages from the input device, 
 * and write the transformation (notes object) to the output device
 */
let degrees = [1, 3, 5, 7] // degrees for a Majur 7th chord
let opts = { 
  start: 0, //start playing when the message is received
  interval: 100, //  arpeggiate the notes (100 millisecs between them)
  duration: 150 // duration of each note is 150 milliseconds
}

// create the midi input object
const input = new midi.Input()

// when a note is recieved, play an M7 arpeggio rooted at that note
input.on('message', (deltaTime, message) => {
  if ((message[0]===144) && (message[2] > 0)) {
    let midiNoteNumber = message[1]
    /*
     * the notes will take the input degrees, and shift them so that
     * the root is the midiNoteNumber
     */
    let notes = chords.degreesToMidi(degrees,
      {shift: midiNoteNumber, defaultOctave: 0})
    mu.play(port, notes, {...opts, velocity: message[2],
      text: 'MIDI note ' + midiNoteNumber})
  }
});
 
// open the port associated with the midi keyboard
input.openPort(4);

mustemi's People

Contributors

billmoser avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

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.