UNPKG

maia-util

Version:

Utility math and music functions supporting various applications by Music Artificial Intelligence Algorithms, Inc.

168 lines (147 loc) 6.29 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.krumhansl_and_kessler_key_profiles = exports.aarden_key_profiles = undefined; exports.fifth_steps_mode = fifth_steps_mode; var _copy_array_object = require('./copy_array_object'); var _copy_array_object2 = _interopRequireDefault(_copy_array_object); var _count_rows = require('./count_rows'); var _count_rows2 = _interopRequireDefault(_count_rows); var _max_argmax = require('./max_argmax'); var _max_argmax2 = _interopRequireDefault(_max_argmax); var _corr = require('./corr'); var _corr2 = _interopRequireDefault(_corr); var _cyclically_permute_array_by = require('./cyclically_permute_array_by'); var _cyclically_permute_array_by2 = _interopRequireDefault(_cyclically_permute_array_by); var _orthogonal_projection_not_unique_equalp = require('./orthogonal_projection_not_unique_equalp'); var _orthogonal_projection_not_unique_equalp2 = _interopRequireDefault(_orthogonal_projection_not_unique_equalp); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // Keyscape. // Setup the key profiles. var key_names = ["C major", "Db major", "D major", "Eb major", "E major", "F major", "Gb major", "G major", "Ab major", "A major", "Bb major", "B major", "C minor", "C# minor", "D minor", "Eb minor", "E minor", "F minor", "F# minor", "G minor", "G# minor", "A minor", "Bb minor", "B minor"]; var aarden_key_profiles = exports.aarden_key_profiles = {}; for (var ikey = 0; ikey < 12; ikey++) { aarden_key_profiles[key_names[ikey]] = (0, _cyclically_permute_array_by2.default)([17.77, 0.15, 14.93, 0.16, 19.8, 11.36, 0.29, 22.06, 0.15, 8.15, 0.23, 4.95], -ikey); } for (var _ikey = 12; _ikey < 24; _ikey++) { aarden_key_profiles[key_names[_ikey]] = (0, _cyclically_permute_array_by2.default)([18.26, 0.74, 14.05, 16.86, 0.7, 14.44, 0.7, 18.62, 4.57, 1.93, 7.38, 1.76], -_ikey); } var krumhansl_and_kessler_key_profiles = exports.krumhansl_and_kessler_key_profiles = {}; for (var _ikey2 = 0; _ikey2 < 12; _ikey2++) { krumhansl_and_kessler_key_profiles[key_names[_ikey2]] = (0, _cyclically_permute_array_by2.default)([6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88], -_ikey2); } for (var _ikey3 = 12; _ikey3 < 24; _ikey3++) { krumhansl_and_kessler_key_profiles[key_names[_ikey3]] = (0, _cyclically_permute_array_by2.default)([6.33, 2.68, 3.52, 5.38, 2.6, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17], -_ikey3); } /** * This function is an implementation of the Krumhansl-Schmuckler key-finding * algorithm. It returns a key estimate for the input points. * * @author Tom Collins and Christian Coulon * @comment 6th November 2015 * @tutorial key-estimation-1 * @param {PointSet} point_set - A point set * @param {number[][]} key_profiles - An array of arrays of 12-element vectors, * where each vector is a cylic permutation of its neighbour. These are * empirically derived weightings of the pitch-class content of each of the * major and minor keys. There is a choice between * `krumhansl_and_kessler_key_profiles` and `aarden_key_profiles`, which have * different weightings. * @param {number} [MNN_idx=1] - The dimension of MIDI note numbers in `ps` * @param {number} [dur_idx=2] - The dimension of durations in `ps` * @return {Object} [string, number, number, number] An array whose first * element is a key name (e.g., "C major" for C major), whose second element is * the maximum correlation value, whose third element is steps on the circle of * fifths (e.g., -1 for F major), and whose fourth element is mode (e.g., 5 for * minor/Aeolian). So for instance, a key estimate of A minor might have output * `["A minor", .8, 3, 5]`. * * @example * var ps = [ * [0, 56, 1], * [0.5, 60, 1], * [1, 58, 1], * [1.5, 61, 1], * [2, 60, 1], * [2.5, 63, 1], * [3, 61, 1], * [3.5, 65, 1], * [4, 63, 1], * [4.5, 67, 1], * [5, 65, 1], * [5.5, 68, 1], * [6, 67, 1], * [6.5, 70, 1], * [7, 68, 2] * ]; * fifth_steps_mode(ps, krumhansl_and_kessler_key_profiles) * → * [ * "Ab major", // Estimated key * 0.90135, // Winning (maximal) correlation * -4, // Steps on the circle of fifths for Ab * 0 // Mode (major/Ionian) * ] */ function fifth_steps_mode(point_set, key_profiles, MNN_idx, dur_idx) { if (MNN_idx == undefined) { MNN_idx = 1; } if (dur_idx == undefined) { dur_idx = 2; } // Copy the point_set variable. var pts = (0, _copy_array_object2.default)(point_set); // Convert the MNNs to MNNs mod 12. for (var i = 0; i < pts.length; i++) { pts[i][MNN_idx] = pts[i][MNN_idx] % 12; } // Get the MNN12s and durations in an array. Begin by constructing the // indicator to pass to orthogonal_projection_not_unique_equalp. var indicator = []; for (var _i = 0; _i < pts[0].length; _i++) { if (_i == MNN_idx || _i == dur_idx) { indicator[_i] = 1; } else { indicator[_i] = 0; } } var arr = (0, _orthogonal_projection_not_unique_equalp2.default)(pts, indicator); var wght_idx = void 0; // Form a distribution over the MNN12s, weighted by duration. if (dur_idx >= MNN_idx) { wght_idx = 1; } else { wght_idx = 0; } var MNN12_and_distbn = (0, _count_rows2.default)(arr, wght_idx); // Convert to a key profile. var idxs = []; for (var _i2 = 0; _i2 < MNN12_and_distbn[0].length; _i2++) { idxs.push(MNN12_and_distbn[0][_i2][0]); } var kp = []; for (var _i3 = 0; _i3 < 12; _i3++) { kp[_i3] = 0; } for (var _i4 = 0; _i4 < idxs.length; _i4++) { kp[idxs[_i4]] = MNN12_and_distbn[1][_i4]; } // Calculate the correlation between the empirical key profile and each of // the theoretical key profiles. var key_names = Object.keys(key_profiles); var r = []; for (var _i5 = 0; _i5 < 24; _i5++) { r[_i5] = (0, _corr2.default)(kp, key_profiles[key_names[_i5]]); } // Prepare the return in terms of fith steps and mode. var corr_and_key = (0, _max_argmax2.default)(r); var quasi_key = corr_and_key[1]; var steps = [0, -5, 2, -3, 4, -1, 6, 1, -4, 3, -2, 5]; var mode = 0; if (quasi_key >= 12) { mode = 5; } return [key_names[quasi_key], corr_and_key[0], steps[quasi_key % 12], mode]; }