maia-features

0.0.7 • Public • Published

MAIA Features

Feature extraction functions supporting various applications by Music Artificial Intelligence Algorithms, Inc.

Local Installation

Set yourself up with an installation of Node.js. Then open up a terminal window and navigate to a directory where you want to experiment with MAIA Features.

User

In the terminal window, execute

npm install maia-features --save

which should make a node_modules folder that contains MAIA Features and its dependencies.

Make yourself a new JavaScript (plain-text) file – Atom is a good editor for such purposes – and copy/paste the first three lines of code from the hello-world example below. Save the file as something like hello_world.js at the same level as node_modules (not inside it).

Return to the terminal and execute

node test/pattern_importance.js

which should run the pattern_importance.js script, giving the output

ans: {
  coeffs: {
    Intercept: 4.277867,
    Compactness: 3.422478734,
    'Norm expected occurrences': -0.038536808,
    'Compression ratio': 0.651073171
  },
  varVals: {
    Intercept: 1,
    Compactness: 0.5,
    'Norm expected occurrences': 75.5194588957674,
    'Compression ratio': 1.5
  },
  estimate: 4.0554372357699195
}

You have started to use MAIA Features!

Developer

With Node.js set up, clone the MAIA Features repository from here and run npm install to acquire the dependencies. Some packages, such as Rollup, might need a general install.

Please follow these steps when making additions or changes:

  1. Additions or changes to the code should be made in the es6 folder;
  2. When documenting, follow the JSDoc format used therein;
  3. Write unit tests below each method/function;
  4. Execute npm run compile to convert the various components in the es6 into the corresponding components in the dist folder, and to combine them into an IIFE (called maia-features.js, in the root of the repository);
  5. Execute jsdoc --configure .jsdoc.config.js es6 to update the documentation, which gets written to the docs folder, and check it looks good and reads well;
  6. Say in step 1 you added a new file to the es6 folder called hello_world.js, then now it's time to check on your unit tests by executing node hello_world.js and seeing whether the console.log()s match your expected output;
  7. Once you are satisfied with your unit tests, comment them out and paste them to test/index.js, following the chai format used therein. Execute npm test to verify that there are ticks everywhere and in particular that your new tests are being invoked;
  8. Do the usual git add ., git commit -m "Short meaningful message", and git push, and we'll see it on the other side as a pull request;
  9. There should not be any need for you to edit the version in package.json;
  10. Please keep any data files out of the repository by editing the .gitignore file.

Hello-world example

const mf = require('maia-features')
// Load a Composition object
const co = {
  "id": "nothing_much_comp",
  // Other metadata omitted for brevity.
  "layer": [
    { "type": "instrument", "idInstrument": "acoustic_grand_piano", "staffNo": 0 }
  ],
  "keySignatures": [
    { "barNo": 1, "keyName": "Db major", "fifthSteps": -5, "mode": 0, "staffNo": 0, "ontime": 0 }
  ],
  "timeSignatures": [
    { "barNo": 1, "topNo": 4, "bottomNo": 4, "ontime": 0 }
  ],
  "tempi": [
    { "id": "dfgkdfgdfgk", "ontime": 0, "barNo": 1, "bpm": 108, "stampDelete": null }
  ],
  "clefChanges": [
    { "barNo": 1, "ontime": 0, "clef": "treble clef", "clefSign": "G", "clefLine": 2, "staffNo": 0 }
  ],
  "notes": [
    {
      "ontime": 0,
      "MNN": 60,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 60,
      "pitch": "C4",
      "stampCreate": 1583938362043,
      "stampDelete": null
    },
    {
      "ontime": 1,
      "MNN": 66,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 63,
      "pitch": "F#4",
      "stampCreate": 1583938365344,
      "stampDelete": null
    },
    {
      "ontime": 2,
      "MNN": 66,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 63,
      "pitch": "F#4",
      "stampCreate": 1583938366479,
      "stampDelete": null
    },
    {
      "ontime": 3,
      "MNN": 60,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 59,
      "pitch": "B#3",
      "stampCreate": 1583938368294,
      "stampDelete": null
    },
    {
      "ontime": 4,
      "MNN": 61,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 60,
      "pitch": "C#4",
      "stampCreate": 1583938371677,
      "stampDelete": 1583938382196
    },
    {
      "ontime": 4,
      "MNN": 61,
      "duration": 3,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 60,
      "pitch": "C#4",
      "stampCreate": 1583938389771,
      "stampDelete": 1583938394202
    },
    {
      "ontime": 4,
      "MNN": 61,
      "duration": 2,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 60,
      "pitch": "C#4",
      "stampCreate": 1583938400462,
      "stampDelete": null
    },
    {
      "ontime": 6,
      "MNN": 60,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 59,
      "pitch": "B#3",
      "stampCreate": 1583938403022,
      "stampDelete": null
    },
    {
      "ontime": 7,
      "MNN": 63,
      "duration": 2,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 61,
      "pitch": "D#4",
      "stampCreate": 1583938408702,
      "stampDelete": null
    },
    {
      "ontime": 9,
      "MNN": 60,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "MPN": 59,
      "pitch": "B#3",
      "stampCreate": 1583938412600,
      "stampDelete": null
    },
    {
      "ontime": 10,
      "MNN": 61,
      "duration": 2,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 60,
      "pitch": "C#4",
      "stampCreate": 1583938415007,
      "stampDelete": null
    },
    {
      "ontime": 12,
      "MNN": 61,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "voiceNo": 0,
      "MPN": 61,
      "pitch": "Db4",
      "stampCreate": 1583938420873,
      "stampDelete": null
    },
    {
      "ontime": 13,
      "MNN": 66,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "MPN": 64,
      "pitch": "Gb4",
      "stampCreate": 1583938424072,
      "stampDelete": null
    },
    {
      "ontime": 14,
      "MNN": 60,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "MPN": 59,
      "pitch": "B#3",
      "stampCreate": 1583938427223,
      "stampDelete": null
    },
    {
      "ontime": 15,
      "MNN": 60,
      "duration": 1,
      "velocity": 0.5,
      "staffNo": 0,
      "MPN": 60,
      "pitch": "C4",
      "stampCreate": 1583938428330,
      "stampDelete": null
    }
  ]
}

// Define an example pattern occurrence and occurrence set, and obtain the
// estimated noticeability/importance of the pattern according to Collins et
// al.'s (2011) Music Perception paper.
let mo = new mf.Model(co)
const myPatternOccurrence = [[4, 61], [9, 60]]
const myOccurrenceSet = [
  [[0, 60], [6, 60]],
  [[4, 61], [9, 60]],
  [[10, 61], [15, 60]]
]
const myMode = "points" // Patterns defined in terms of points rather than indices.
// The Model object holds a reference to the Composition object. This has a
// points property, but it probably represents more dimensions than you want for
// the patterns, which are typically defined in terms of (ontime, MNN)- or
// (ontime, MPN)-pairs. Therefore, you need to "project" the point set
// representing the whole piece into this lower-dimensional space before trying
// to apply the rating formula.
const myProjectedDataset = mo.compObj.points.map(function(pt){
  return [pt[mo.compObj.ontimeIdx], pt[mo.compObj.mnnIdx]]
})
// console.log("myProjectedDataset:", myProjectedDataset)
const myTfPitch = true // (ontime, pitch)-patterns as opposed to (ontime, duration)-patterns.

const ans = mo.get_model(
  "Music Perception 2011",
  {
    "pOcc": myPatternOccurrence,
    "occSet": myOccurrenceSet,
    "mode": myMode,
    "projDSet": myProjectedDataset,
    "tfPitch": myTfPitch
  }
)
console.log("ans:", ans)

Tests

TBD

Contributing

TBD

Release History

  • 0.0.6-7 Added some features from Yang and Lerch (2020).
  • 0.0.1-5 MCEC 2020 features committed, as well as Music Perception 2011 noticeability/importance formula.
  • 0.0.0 Initial release

Package Sidebar

Install

npm i maia-features

Weekly Downloads

0

Version

0.0.7

License

AGPL-3.0-or-later

Unpacked Size

343 kB

Total Files

22

Last publish

Collaborators

  • tomthecollins