UNPKG

edo.js

Version:

A set of functions for manipulating musical pitches within a given EDO

744 lines (630 loc) 455 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>edo.js</title> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/third-party/ionicons.min.css"> <link type="text/css" rel="stylesheet" href="styles/third-party/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> <link type="text/css" rel="stylesheet" href="styles/clean-jsdoc-theme-base.css"> <link type="text/css" rel="stylesheet" href="styles/clean-jsdoc-theme-light.css"> <svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"> <defs> <symbol id="copy-icon" viewbox="0 0 488.3 488.3"> <g> <path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/> <path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/> </g> </symbol> </defs> </svg> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav> <h2><a href="index.html"><div class="text">Home</div></a></h2><div class="search-box"><input type="text" placeholder="Search..." id="search-box" /><div class="search-item-container" id="search-item-container"><ul class="search-item-ul" id="search-item-ul"></ul></div></div><div class="sidebar-list-div"><h3>Classes</h3><ul><li><a href="EDO.html">EDO</a><ul class='methods'><li data-type='method'><a href="EDO.html#scale">scale</a></li></ul></li><li><a href="Scale.html">Scale</a><ul class='methods'><li data-type='method'><a href="Scale.html#complement">complement</a></li><li data-type='method'><a href="Scale.html#invert">invert</a></li><li data-type='method'><a href="Scale.html#mode">mode</a></li><li data-type='method'><a href="Scale.html#normal">normal</a></li><li data-type='method'><a href="Scale.html#prime">prime</a></li></ul></li><li><a href="Time.html">Time</a></li></ul><h3>Namespaces</h3><ul><li><a href="EDO_convert.html">convert</a><ul class='methods'><li data-type='method'><a href="EDO_convert.html#.cents_to_interval">cents_to_interval</a></li><li data-type='method'><a href="EDO_convert.html#.cents_to_ratio">cents_to_ratio</a></li><li data-type='method'><a href="EDO_convert.html#.freq_to_midi">freq_to_midi</a></li><li data-type='method'><a href="EDO_convert.html#.interval_to_cents">interval_to_cents</a></li><li data-type='method'><a href="EDO_convert.html#.interval_to_ratio">interval_to_ratio</a></li><li data-type='method'><a href="EDO_convert.html#.intervals_to_pitches">intervals_to_pitches</a></li><li data-type='method'><a href="EDO_convert.html#.intervals_to_scale">intervals_to_scale</a></li><li data-type='method'><a href="EDO_convert.html#.midi_to_freq">midi_to_freq</a></li><li data-type='method'><a href="EDO_convert.html#.midi_to_intervals">midi_to_intervals</a></li><li data-type='method'><a href="EDO_convert.html#.midi_to_name">midi_to_name</a></li><li data-type='method'><a href="EDO_convert.html#.name_to_scale">name_to_scale</a></li><li data-type='method'><a href="EDO_convert.html#.pc_to_name">pc_to_name</a></li><li data-type='method'><a href="EDO_convert.html#.pitches_to_freq">pitches_to_freq</a></li><li data-type='method'><a href="EDO_convert.html#.pitches_to_PCs">pitches_to_PCs</a></li><li data-type='method'><a href="EDO_convert.html#.ratio_to_cents">ratio_to_cents</a></li><li data-type='method'><a href="EDO_convert.html#.ratio_to_interval">ratio_to_interval</a></li><li data-type='method'><a href="EDO_convert.html#.to_steps">to_steps</a></li></ul></li><li><a href="EDO_count.html">count</a><ul class='methods'><li data-type='method'><a href="EDO_count.html#.common_tones">common_tones</a></li><li data-type='method'><a href="EDO_count.html#.differences">differences</a></li><li data-type='method'><a href="EDO_count.html#.pitches">pitches</a></li></ul></li><li><a href="EDO_export.html">export</a><ul class='methods'><li data-type='method'><a href="EDO_export.html#.png">png</a></li><li data-type='method'><a href="EDO_export.html#.svg">svg</a></li></ul></li><li><a href="EDO_get.html">get</a><ul class='methods'><li data-type='method'><a href="EDO_get.html#.angle">angle</a></li><li data-type='method'><a href="EDO_get.html#.best_edo_from_cents">best_edo_from_cents</a></li><li data-type='method'><a href="EDO_get.html#.combinations">combinations</a></li><li data-type='method'><a href="EDO_get.html#.complementary_interval">complementary_interval</a></li><li data-type='method'><a href="EDO_get.html#.complementary_set">complementary_set</a></li><li data-type='method'><a href="EDO_get.html#.contour">contour</a></li><li data-type='method'><a href="EDO_get.html#.contour_motives">contour_motives</a></li><li data-type='method'><a href="EDO_get.html#.coordinates">coordinates</a></li><li data-type='method'><a href="EDO_get.html#.evenly_split">evenly_split</a></li><li data-type='method'><a href="EDO_get.html#.fill_partial_harp_pedaling">fill_partial_harp_pedaling</a></li><li data-type='method'><a href="EDO_get.html#.generated_scale">generated_scale</a></li><li data-type='method'><a href="EDO_get.html#.generators">generators</a></li><li data-type='method'><a href="EDO_get.html#.harmonic_progression">harmonic_progression</a></li><li data-type='method'><a href="EDO_get.html#.harmonized_melody">harmonized_melody</a></li><li data-type='method'><a href="EDO_get.html#.harp_pedals_to_pitches">harp_pedals_to_pitches</a></li><li data-type='method'><a href="EDO_get.html#.harp_position_of_quality">harp_position_of_quality</a></li><li data-type='method'><a href="EDO_get.html#.intersection">intersection</a></li><li data-type='method'><a href="EDO_get.html#.interval_stack">interval_stack</a></li><li data-type='method'><a href="EDO_get.html#.interval_traversed">interval_traversed</a></li><li data-type='method'><a href="EDO_get.html#.inversion">inversion</a></li><li data-type='method'><a href="EDO_get.html#.lattice">lattice</a></li><li data-type='method'><a href="EDO_get.html#.levenshtein">levenshtein</a></li><li data-type='method'><a href="EDO_get.html#.maximal_carey_coherence_failures">maximal_carey_coherence_failures</a></li><li data-type='method'><a href="EDO_get.html#.maximal_rahn_difference">maximal_rahn_difference</a></li><li data-type='method'><a href="EDO_get.html#.minimal_voice_leading">minimal_voice_leading</a></li><li data-type='method'><a href="EDO_get.html#.mixture_in_cardinality">mixture_in_cardinality</a></li><li data-type='method'><a href="EDO_get.html#.modes">modes</a></li><li data-type='method'><a href="EDO_get.html#.motives">motives</a></li><li data-type='method'><a href="EDO_get.html#.n_choose_k">n_choose_k</a></li><li data-type='method'><a href="EDO_get.html#.necklace">necklace</a></li><li data-type='method'><a href="EDO_get.html#.new_pitches">new_pitches</a></li><li data-type='method'><a href="EDO_get.html#.ngrams">ngrams</a></li><li data-type='method'><a href="EDO_get.html#.normal_order">normal_order</a></li><li data-type='method'><a href="EDO_get.html#.notes_from_cents">notes_from_cents</a></li><li data-type='method'><a href="EDO_get.html#.partitioned_subsets">partitioned_subsets</a></li><li data-type='method'><a href="EDO_get.html#.path_n_steps">path_n_steps</a></li><li data-type='method'><a href="EDO_get.html#.path_on_tree">path_on_tree</a></li><li data-type='method'><a href="EDO_get.html#.permutations">permutations</a></li><li data-type='method'><a href="EDO_get.html#.pitch_distribution">pitch_distribution</a></li><li data-type='method'><a href="EDO_get.html#.pitch_fields">pitch_fields</a></li><li data-type='method'><a href="EDO_get.html#.random_melody">random_melody</a></li><li data-type='method'><a href="EDO_get.html#.random_melody_from_contour">random_melody_from_contour</a></li><li data-type='method'><a href="EDO_get.html#.random_melody_from_distribution">random_melody_from_distribution</a></li><li data-type='method'><a href="EDO_get.html#.random_melody_from_ngram">random_melody_from_ngram</a></li><li data-type='method'><a href="EDO_get.html#.ratio_approximation">ratio_approximation</a></li><li data-type='method'><a href="EDO_get.html#.retrograde">retrograde</a></li><li data-type='method'><a href="EDO_get.html#.rotated">rotated</a></li><li data-type='method'><a href="EDO_get.html#.rotations">rotations</a></li><li data-type='method'><a href="EDO_get.html#.scalar_melodies">scalar_melodies</a></li><li data-type='method'><a href="EDO_get.html#.scale_fragments">scale_fragments</a></li><li data-type='method'><a href="EDO_get.html#.scales">scales</a></li><li data-type='method'><a href="EDO_get.html#.sets_from_mixture">sets_from_mixture</a></li><li data-type='method'><a href="EDO_get.html#.shortest_path">shortest_path</a></li><li data-type='method'><a href="EDO_get.html#.simple_ratios">simple_ratios</a></li><li data-type='method'><a href="EDO_get.html#.stacked">stacked</a></li><li data-type='method'><a href="EDO_get.html#.starting_at">starting_at</a></li><li data-type='method'><a href="EDO_get.html#.step_maximal_mean_error_in_cardinality">step_maximal_mean_error_in_cardinality</a></li><li data-type='method'><a href="EDO_get.html#.step_min_max_error_in_EDO">step_min_max_error_in_EDO</a></li><li data-type='method'><a href="EDO_get.html#.step_min_max_mean_error_in_cardinality">step_min_max_mean_error_in_cardinality</a></li><li data-type='method'><a href="EDO_get.html#.step_minimal_mean_error_in_cardinality">step_minimal_mean_error_in_cardinality</a></li><li data-type='method'><a href="EDO_get.html#.subset_indices">subset_indices</a></li><li data-type='method'><a href="EDO_get.html#.subsets">subsets</a></li><li data-type='method'><a href="EDO_get.html#.transposition">transposition</a></li><li data-type='method'><a href="EDO_get.html#.union">union</a></li><li data-type='method'><a href="EDO_get.html#.unique_elements">unique_elements</a></li><li data-type='method'><a href="EDO_get.html#.well_formed_scale">well_formed_scale</a></li><li data-type='method'><a href="EDO_get.html#.without">without</a></li><li data-type='method'><a href="EDO_get.html#.without_chromatic_notes">without_chromatic_notes</a></li></ul></li><li><a href="EDO_is.html">is</a><ul class='methods'><li data-type='method'><a href="EDO_is.html#.element_of">element_of</a></li><li data-type='method'><a href="EDO_is.html#.rotation">rotation</a></li><li data-type='method'><a href="EDO_is.html#.same">same</a></li><li data-type='method'><a href="EDO_is.html#.subset">subset</a></li><li data-type='method'><a href="EDO_is.html#.transposition">transposition</a></li></ul></li><li><a href="EDO_midi.html">midi</a><ul class='methods'><li data-type='method'><a href="EDO_midi.html#.chordify">chordify</a></li><li data-type='method'><a href="EDO_midi.html#.import">import</a></li><li data-type='method'><a href="EDO_midi.html#.strip">strip</a></li></ul></li><li><a href="EDO_show.html">show</a><ul class='methods'><li data-type='method'><a href="EDO_show.html#.contour">contour</a></li><li data-type='method'><a href="EDO_show.html#.interval_fractal_tree">interval_fractal_tree</a></li><li data-type='method'><a href="EDO_show.html#.necklace">necklace</a></li><li data-type='method'><a href="EDO_show.html#.necklace_fractal">necklace_fractal</a></li><li data-type='method'><a href="EDO_show.html#.nested_necklaces">nested_necklaces</a></li></ul></li><li><a href="EDO_xml.html">xml</a></li><li><a href="Scale_count.html">count</a><ul class='methods'><li data-type='method'><a href="Scale_count.html#.chord_quality">chord_quality</a></li><li data-type='method'><a href="Scale_count.html#.consecutive_steps">consecutive_steps</a></li><li data-type='method'><a href="Scale_count.html#.imperfections">imperfections</a></li><li data-type='method'><a href="Scale_count.html#.interval">interval</a></li><li data-type='method'><a href="Scale_count.html#.M3s">M3s</a></li><li data-type='method'><a href="Scale_count.html#.m3s">m3s</a></li><li data-type='method'><a href="Scale_count.html#.major_minor_triads">major_minor_triads</a></li><li data-type='method'><a href="Scale_count.html#.min_max_n_chords_in_necklace">min_max_n_chords_in_necklace</a></li><li data-type='method'><a href="Scale_count.html#.modes">modes</a></li><li data-type='method'><a href="Scale_count.html#.n_chords">n_chords</a></li><li data-type='method'><a href="Scale_count.html#.n_chords_diatonic">n_chords_diatonic</a></li><li data-type='method'><a href="Scale_count.html#.P5s">P5s</a></li><li data-type='method'><a href="Scale_count.html#.pitches">pitches</a></li><li data-type='method'><a href="Scale_count.html#.rahn_ambiguities">rahn_ambiguities</a></li><li data-type='method'><a href="Scale_count.html#.rahn_contradictions">rahn_contradictions</a></li><li data-type='method'><a href="Scale_count.html#.rahn_differences">rahn_differences</a></li><li data-type='method'><a href="Scale_count.html#.ratio">ratio</a></li><li data-type='method'><a href="Scale_count.html#.rotational_symmetries">rotational_symmetries</a></li><li data-type='method'><a href="Scale_count.html#.simple_ratios">simple_ratios</a></li><li data-type='method'><a href="Scale_count.html#.tetrachords">tetrachords</a></li><li data-type='method'><a href="Scale_count.html#.thirds">thirds</a></li><li data-type='method'><a href="Scale_count.html#.transpositions">transpositions</a></li><li data-type='method'><a href="Scale_count.html#.trichords">trichords</a></li><li data-type='method'><a href="Scale_count.html#.unique_elements">unique_elements</a></li></ul></li><li><a href="Scale_export.html">export</a><ul class='methods'><li data-type='method'><a href="Scale_export.html#.scala">scala</a></li></ul></li><li><a href="Scale_get.html">get</a><ul class='methods'><li data-type='method'><a href="Scale_get.html#.area">area</a></li><li data-type='method'><a href="Scale_get.html#.binary_unevenness">binary_unevenness</a></li><li data-type='method'><a href="Scale_get.html#.cardinality_variety_ratio">cardinality_variety_ratio</a></li><li data-type='method'><a href="Scale_get.html#.chord_quality_from_shape">chord_quality_from_shape</a></li><li data-type='method'><a href="Scale_get.html#.coherence_quotient">coherence_quotient</a></li><li data-type='method'><a href="Scale_get.html#.common_tone_transpositions">common_tone_transpositions</a></li><li data-type='method'><a href="Scale_get.html#.complement">complement</a></li><li data-type='method'><a href="Scale_get.html#.constituent_similarity">constituent_similarity</a></li><li data-type='method'><a href="Scale_get.html#.coordinates">coordinates</a></li><li data-type='method'><a href="Scale_get.html#.diagnostic_combinations">diagnostic_combinations</a></li><li data-type='method'><a href="Scale_get.html#.diagnostic_intervals">diagnostic_intervals</a></li><li data-type='method'><a href="Scale_get.html#.edo">edo</a></li><li data-type='method'><a href="Scale_get.html#.entropy">entropy</a></li><li data-type='method'><a href="Scale_get.html#.evenness_of_spread">evenness_of_spread</a></li><li data-type='method'><a href="Scale_get.html#.generic_intervals">generic_intervals</a></li><li data-type='method'><a href="Scale_get.html#.identity_fragment">identity_fragment</a></li><li data-type='method'><a href="Scale_get.html#.information">information</a></li><li data-type='method'><a href="Scale_get.html#.interval_class">interval_class</a></li><li data-type='method'><a href="Scale_get.html#.interval_vector">interval_vector</a></li><li data-type='method'><a href="Scale_get.html#.inversion">inversion</a></li><li data-type='method'><a href="Scale_get.html#.least_step_multiplier">least_step_multiplier</a></li><li data-type='method'><a href="Scale_get.html#.lerdahl_attraction">lerdahl_attraction</a></li><li data-type='method'><a href="Scale_get.html#.lerdahl_attraction_vector">lerdahl_attraction_vector</a></li><li data-type='method'><a href="Scale_get.html#.levenshtein">levenshtein</a></li><li data-type='method'><a href="Scale_get.html#.mean">mean</a></li><li data-type='method'><a href="Scale_get.html#.melody_from_intervals">melody_from_intervals</a></li><li data-type='method'><a href="Scale_get.html#.minimal_diagnostic_combination">minimal_diagnostic_combination</a></li><li data-type='method'><a href="Scale_get.html#.mixture">mixture</a></li><li data-type='method'><a href="Scale_get.html#.mode_variance">mode_variance</a></li><li data-type='method'><a href="Scale_get.html#.modes">modes</a></li><li data-type='method'><a href="Scale_get.html#.modes_with_notes">modes_with_notes</a></li><li data-type='method'><a href="Scale_get.html#.motives_diatonic">motives_diatonic</a></li><li data-type='method'><a href="Scale_get.html#.n_chords">n_chords</a></li><li data-type='method'><a href="Scale_get.html#.n_chords_diatonic">n_chords_diatonic</a></li><li data-type='method'><a href="Scale_get.html#.name">name</a></li><li data-type='method'><a href="Scale_get.html#.necklace_family">necklace_family</a></li><li data-type='method'><a href="Scale_get.html#.necklace_family_members">necklace_family_members</a></li><li data-type='method'><a href="Scale_get.html#.neighborhood">neighborhood</a></li><li data-type='method'><a href="Scale_get.html#.normal_order">normal_order</a></li><li data-type='method'><a href="Scale_get.html#.pairwise_generic_specific_intervals">pairwise_generic_specific_intervals</a></li><li data-type='method'><a href="Scale_get.html#.per_note_set_difference">per_note_set_difference</a></li><li data-type='method'><a href="Scale_get.html#.permutations">permutations</a></li><li data-type='method'><a href="Scale_get.html#.pitches">pitches</a></li><li data-type='method'><a href="Scale_get.html#.position_of_quality">position_of_quality</a></li><li data-type='method'><a href="Scale_get.html#.prime_form">prime_form</a></li><li data-type='method'><a href="Scale_get.html#.product">product</a></li><li data-type='method'><a href="Scale_get.html#.quality_with_intervals">quality_with_intervals</a></li><li data-type='method'><a href="Scale_get.html#.reflectional_symmetry">reflectional_symmetry</a></li><li data-type='method'><a href="Scale_get.html#.resize_melody">resize_melody</a></li><li data-type='method'><a href="Scale_get.html#.rotational_symmetry">rotational_symmetry</a></li><li data-type='method'><a href="Scale_get.html#.rotations">rotations</a></li><li data-type='method'><a href="Scale_get.html#.rothenberg_propriety">rothenberg_propriety</a></li><li data-type='method'><a href="Scale_get.html#.roughness">roughness</a></li><li data-type='method'><a href="Scale_get.html#.runs">runs</a></li><li data-type='method'><a href="Scale_get.html#.sameness_quotient">sameness_quotient</a></li><li data-type='method'><a href="Scale_get.html#.scale_degree_roles">scale_degree_roles</a></li><li data-type='method'><a href="Scale_get.html#.scale_degree_transpositions">scale_degree_transpositions</a></li><li data-type='method'><a href="Scale_get.html#.sequence_transposition">sequence_transposition</a></li><li data-type='method'><a href="Scale_get.html#.set_difference">set_difference</a></li><li data-type='method'><a href="Scale_get.html#.shortest_path">shortest_path</a></li><li data-type='method'><a href="Scale_get.html#.sine_pair_dissonance">sine_pair_dissonance</a></li><li data-type='method'><a href="Scale_get.html#.specific_intervals">specific_intervals</a></li><li data-type='method'><a href="Scale_get.html#.stacks">stacks</a></li><li data-type='method'><a href="Scale_get.html#.step_mean_error">step_mean_error</a></li><li data-type='method'><a href="Scale_get.html#.step_similarity">step_similarity</a></li><li data-type='method'><a href="Scale_get.html#.step_sizes">step_sizes</a></li><li data-type='method'><a href="Scale_get.html#.step_tally">step_tally</a></li><li data-type='method'><a href="Scale_get.html#.steps_to_qualities">steps_to_qualities</a></li><li data-type='method'><a href="Scale_get.html#.supersets">supersets</a></li><li data-type='method'><a href="Scale_get.html#.symmetricalness">symmetricalness</a></li><li data-type='method'><a href="Scale_get.html#.tetrachords">tetrachords</a></li><li data-type='method'><a href="Scale_get.html#.transposition">transposition</a></li><li data-type='method'><a href="Scale_get.html#.transpositions_with_pitches">transpositions_with_pitches</a></li><li data-type='method'><a href="Scale_get.html#.trichords">trichords</a></li><li data-type='method'><a href="Scale_get.html#.unevenness">unevenness</a></li><li data-type='method'><a href="Scale_get.html#.without">without</a></li></ul></li><li><a href="Scale_is.html">is</a><ul class='methods'><li data-type='method'><a href="Scale_is.html#.deep">deep</a></li><li data-type='method'><a href="Scale_is.html#.distributionally_even">distributionally_even</a></li><li data-type='method'><a href="Scale_is.html#.in_lower_edos">in_lower_edos</a></li><li data-type='method'><a href="Scale_is.html#.invertible">invertible</a></li><li data-type='method'><a href="Scale_is.html#.maximally_even">maximally_even</a></li><li data-type='method'><a href="Scale_is.html#.mode_of">mode_of</a></li><li data-type='method'><a href="Scale_is.html#.MOLT">MOLT</a></li><li data-type='method'><a href="Scale_is.html#.myhill_property">myhill_property</a></li><li data-type='method'><a href="Scale_is.html#.normal_order">normal_order</a></li><li data-type='method'><a href="Scale_is.html#.one_of">one_of</a></li><li data-type='method'><a href="Scale_is.html#.prime_form">prime_form</a></li><li data-type='method'><a href="Scale_is.html#.sharper">sharper</a></li><li data-type='method'><a href="Scale_is.html#.subset">subset</a></li></ul></li><li><a href="Scale_show.html">show</a><ul class='methods'><li data-type='method'><a href="Scale_show.html#.interval_fractal_tree">interval_fractal_tree</a></li><li data-type='method'><a href="Scale_show.html#.necklace">necklace</a></li></ul></li><li><a href="Scale_to.html">to</a><ul class='methods'><li data-type='method'><a href="Scale_to.html#.cents">cents</a></li><li data-type='method'><a href="Scale_to.html#.EDO">EDO</a></li><li data-type='method'><a href="Scale_to.html#.steps">steps</a></li></ul></li><li><a href="Time_convert.html">convert</a><ul class='methods'><li data-type='method'><a href="Time_convert.html#.beats_to_msec">beats_to_msec</a></li><li data-type='method'><a href="Time_convert.html#.beats_to_ratios">beats_to_ratios</a></li><li data-type='method'><a href="Time_convert.html#.beats_to_tempo">beats_to_tempo</a></li></ul></li><li><a href="Time_get.html">get</a><ul class='methods'><li data-type='method'><a href="Time_get.html#.beat">beat</a></li><li data-type='method'><a href="Time_get.html#.counterpoint_cycle">counterpoint_cycle</a></li><li data-type='method'><a href="Time_get.html#.explicit">explicit</a></li><li data-type='method'><a href="Time_get.html#.fractal">fractal</a></li><li data-type='method'><a href="Time_get.html#.motives">motives</a></li><li data-type='method'><a href="Time_get.html#.ratios">ratios</a></li><li data-type='method'><a href="Time_get.html#.relational_motives">relational_motives</a></li><li data-type='method'><a href="Time_get.html#.repeated">repeated</a></li><li data-type='method'><a href="Time_get.html#.subdivisions">subdivisions</a></li></ul></li><li><a href="Time_resize.html">resize</a><ul class='methods'><li data-type='method'><a href="Time_resize.html#.by_product">by_product</a></li><li data-type='method'><a href="Time_resize.html#.by_sum">by_sum</a></li></ul></li></ul><h3><a href="global.html">Global</a></h3><ul><li><a href="global.html#myhill_property">myhill_property</a></li></ul></div> </nav> <div id="main"> <h1 id='page-title' class="page-title">edo.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>const environment = (typeof window === 'undefined') ? "server" : "browser" // import { createRequire } from "module"; // const require = createRequire(import.meta.url); let fs, parseXML, midiParser if (environment == 'server') { fs = require('fs') parseXML = require('xml2js').parseString; midiParser = require('midi-parser-js'); } let save_file if (environment == 'server') { /** * @ignore*/ save_file = function (name, dir, contents, _unused) { fs.writeFile(dir + name, contents, function (err) { if (err) { return console.log(err); } }); } } else { /** * Handles file saving when run client-side * @ignore * */ save_file = function (name, dir, contents, mime_type = "text/plain") { const blob = new Blob([contents], {type: mime_type}); const dlink = document.createElement('a'); dlink.download = name; dlink.href = window.URL.createObjectURL(blob); dlink.onclick = function (e) { // revokeObjectURL needs a delay to work properly setTimeout(() => { window.URL.revokeObjectURL(this.href); }, 1500); }; dlink.click(); dlink.remove(); } } let load_file if (environment == 'server') { /** * Handles file loading when run server-side * @ignore * */ /** * @ignore*/ load_file = function (file) { return fs.readFileSync(file, // {encoding:'utf8', flag:'r'} ); } } else { /** * Handles file saving when run client-side * @ignore * */ load_file = function (name, dir, contents) { var fileSelector = document.createElement('input'); fileSelector.setAttribute('type', 'file'); var selectDialogueLink = document.createElement('a'); selectDialogueLink.setAttribute('href', ''); selectDialogueLink.innerText = "Select File"; selectDialogueLink.onclick = function () { fileSelector.click(); return false; } selectDialogueLink.click() } } class FixedContentNecklace { constructor(number_list,method="fast") { /* Class FixedContentNecklace Init Method :param number_list: A list of integers */ // Force negative numbers to zero for (let i = 0; i &lt; number_list.length; i++) { if (number_list[i] &lt; 0) number_list[i] = 0 } this.n_init = number_list this.N = number_list.reduce((t, n) => n + t) this.k = number_list.length this.initialize(method) } initialize(method) { /* Determines what method algorithm to use in the generation :param method: The name of the method/algorithm to use */ this.occurrence = [...this.n_init] this.word = Array(this.N).fill(0) this.alphabet = Array(this.k).fill(0) this.alphabet = this.alphabet.map((el, i, arr) => i) this.run = Array(this.N).fill(0) this.first_letter = 0 this.last_letter = this.k - 1 this.__set_letter_bounds(method) if (method != 'simple') { this.word = [this.word[0]].concat(Array(this.N - 1).fill(this.last_letter)) } } __set_letter_bounds(method) { /* Assign the first letter with nonzero occurrence to word[0], short-circuiting the search to the letter to put there during the algorithm, and finds the last nonzero letter :param method: The name of the method/algorithm to use */ let found_first_nonzero = false for (let letter = 0; letter &lt; this.k; letter++) { if (!found_first_nonzero &amp;&amp; this.occurrence[letter] > 0) { found_first_nonzero = true this.occurrence[letter] -= 1 this.word[0] = letter this.first_letter = letter } // remove any letters with zero occurrence from the alphabet so that // we automatically skip them if (method != 'simple') { if (this.occurrence[letter] == 0) { this.__remove_letter(letter) } } } this.last_letter = (!this.alphabet) ? 0 : Math.max.apply(Math, this.alphabet) } * execute(method = "simple") { /* Runs the algorithm that's passed to `method` :param method: The method/algorithm to execute */ this.initialize(method) if (method == 'simple') { yield* this._simple_fixed_content(2, 1) } else if (method == 'fast') { yield* this._fast_fixed_content(2, 1, 2) } } * _simple_fixed_content(t, p) { /* The simple algorithm :param t: ? :param p: ? */ if (t > this.N) { // if the prenecklace is complete if (this.N % p == 0) { // if the prenecklace word is a necklace yield [...this.word] } } else { for (let letter = this.word[t - p - 1]; letter &lt; this.k; letter++) { if (this.occurrence[letter] > 0) { this.word[t - 1] = letter this.occurrence[letter] -= 1 if (letter == this.word[t - p - 1]) { yield* this._simple_fixed_content(t + 1, p) } else { yield* this._simple_fixed_content(t + 1, t) } this.occurrence[letter] += 1 } } } } * _fast_fixed_content(t, p, s) { let i_removed /* The fast algorithm */ if (this.occurrence[this.last_letter] == this.N - t + 1) { if (this.occurrence[this.last_letter] == this.run[t - p - 1]) { if (this.N % p == 0) { yield [...this.word] } } else if (this.occurrence[this.last_letter] > this.run[t - p - 1]) { yield [...this.word] } } else if (this.occurrence[this.first_letter] != this.N - t + 1) { let letter = Math.max.apply(Math, this.alphabet) let i = this.alphabet.length - 1 let s_current = s while (letter >= this.word[t - p - 1]) { this.run[parseInt(s - 1)] = parseInt(t - s) this.word[t - 1] = letter this.occurrence[letter] -= 1 if (!this.occurrence[letter]) { i_removed = this.__remove_letter(letter) } if (letter != this.last_letter) { s_current = t + 1 } if (letter == this.word[t - p - 1]) { yield* this._fast_fixed_content(t + 1, p, s_current) } else { yield* this._fast_fixed_content(t + 1, t, s_current) } if (!this.occurrence[letter]) { this.__add_letter(i_removed, letter) } this.occurrence[letter] += 1 i -= 1 letter = this.__get_letter(i) } this.word[t - 1] = this.last_letter } } __remove_letter(letter) { let index = this.alphabet.indexOf(letter) this.alphabet.splice(index, 1) return index } __add_letter(index, letter) { this.alphabet.splice(index, 0, letter) } __get_letter(index) { return (index &lt; 0) ? -1 : this.alphabet[index] } } const combinations = (set, k) => { if (k > set.length || k &lt;= 0) { return [] } if (k == set.length) { return [set] } if (k == 1) { return set.reduce((acc, cur) => [...acc, [cur]], []) } let combs = [], tail_combs = [] for (let i = 0; i &lt;= set.length - k + 1; i++) { tail_combs = combinations(set.slice(i + 1), k - 1) for (let j = 0; j &lt; tail_combs.length; j++) { combs.push([set[i], ...tail_combs[j]]) } } return combs } const unique_in_array = (base) => [...new Set(base)] const rescale = (num, in_min, in_max, out_min, out_max) => { return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } const GCD = (...n) => n.length === 2 ? n[1] ? GCD(n[1], n[0] % n[1]) : n[0] : n.reduce((a, c) => a = GCD(a, c)); /** Class representing some EDO tuning system.*/ class EDO { /** * &lt;p>Creates a tuning context and system that exposes powerful functions for manipulating, analyzing, and generating music.&lt;/p> * &lt;p>This is the main class of the project. At its center stand 7 collections (see "Namespaces" below) of functions.&lt;/p> * &lt;ul> * &lt;li> [EDO.convert]{@link EDO#convert} is a set of functions used to change between equivalent representations within the tuning context.&lt;/li> * &lt;li> [EDO.count]{@link EDO#count} is a set of functions used to count stuff.&lt;/li> * &lt;li> [EDO.get]{@link EDO#get} is a set of functions used to manipulate and generate stuff.&lt;/li> * &lt;li> [EDO.is]{@link EDO#is} is a set of functions used for boolean truth statements.&lt;/li> * &lt;li> [EDO.show]{@link EDO#show} is a set of functions used for visualization.&lt;/li> * &lt;li> [EDO.midi]{@link EDO#midi} is a set of functions used for importing and processing midi files.&lt;/li> * &lt;li> [EDO.xml]{@link EDO#xml} is a set of functions used for- importing and processing musicXML files.&lt;/li> * &lt;li> [EDO.export]{@link EDO#export} is a set of functions used for exporting the output to various formats.&lt;/li> * &lt;/ul> * @param {number} edo - The number of equal divisions of the octave. * @example * //Basic usage: * let edo = new EDO(12) //create a new EDO context with 12 divisions. * * //once the object has been created, you can access its functions. * edo.get.inversion([0,2,4,5,7,9,11]) //inverts the pitches * //returns [0, 2, 4, 6, 7, 9, 11] * * edo.convert.ratio_to_interval(3/2) * //returns [7] * * edo.count.pitches([0, 3, 3, 2, 4, 3, 4]) * //returns [[3,3],[4,2], [2,1], [0,1]] (3 appears 3 times, 4 appears 2 times, etc.) * * edo.is.subset([2,4],[1,2,3,4,5]) * //returns true (the set [2,4] IS a subset of [1,2,3,4,5]) */ constructor(edo = 12) { this.edo = edo this.cents_per_step = (12 / edo) * 100 this.M3s = this.convert.ratio_to_interval(5 / 4, 20) this.m3s = this.convert.ratio_to_interval(6 / 5, 20) this.P5s = this.convert.ratio_to_interval(3 / 2, 5) this.edo_divisors = this.get.divisors(edo) this.catalog = {} } /** * &lt;p>Returns a new Scale Object with given pitches&lt;/p> * &lt;p>Remark: "pitch classes" conform to the current tuning system used. 0-11 in 12EDO, 0-16 in 17EDO, etc.&lt;/p> * @param {Array&lt;Number>} pitches - a collection of pitch classes * @return {Scale} */ scale(pitches,cache = this.cache) { return new Scale(pitches, this, cache) } make_DOM_svg(container_id, width, height, clean = false) { let div = document.createElement('div') div.style.width = width + "px"; div.style.height = height + "px"; div.style.display = "inline" let div_id = div.setAttribute("id", "paper_" + Date.now()); let container = document.getElementById(container_id) if (clean) container.innerHTML = "" container.appendChild(div) const paper = new Raphael(div, width, height); let background = paper.rect(0, 0, width, height).attr('fill', '#000000') return { div_id: div_id, div: div, container_id: container_id, container: container, paper: paper, background: background, width: width, height: height, cleaned: clean } } shuffle_array(arr_in, in_place = true) { let arr if (in_place) arr = arr_in else arr = [...arr_in] for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * i) const temp = arr[i] arr[i] = arr[j] arr[j] = temp } return arr } sort_scales = (scales) => { scales = scales.sort((a, b) => { let run = Math.min(a.pitches.length, b.pitches.length) for (let i = 0; i &lt; run; i++) { if (a.pitches[i] != b.pitches[i]) return a.pitches[i] - b.pitches[i] else if (a.pitches[i] == b.pitches[i] &amp;&amp; i == run - 1) return a.pitches.length - b.pitches.length } }) return scales } float_to_rat(x,tolerance = 1.0E-3) { let h1=1, h2=0, k1=0, k2=1; let b = x; do { let a = Math.floor(b); let aux = h1; h1 = a*h1+h2; h2 = aux; aux = k1; k1 = a*k1+k2; k2 = aux; b = 1/(b-a); } while (Math.abs(x-h1/k1) > x*tolerance); return h1+"/"+k1; } /**A collection of functions that convert an input into other equivalent representations * @namespace EDO#convert*/ convert = { /** Expresses cents as intervallic unit (in given EDO) * * @param {Number} interval - cents * @param {Boolean} [round=true] - whether to round the decimals in case not a round number * @returns {Number} An equivilant value represented in intervallic units * @memberOf EDO#convert * @example * let edo = new EDO(24) // define a tuning with 24 divisions of the octave * edo.convert.cents_to_interval(6) * //returns 2*/ cents_to_interval: (cents, round=true) => { let result = cents / this.cents_per_step if(round) result = Math.round(result) return result }, /** Returns a ratio as a decimal number from an interval represented in cents * * @param {Number} cents - an interval in cents * @returns {Number} a ratio * @memberOf EDO#convert * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.cents_to_ratio(700) * // returns 1.4983070768766815*/ cents_to_ratio: (cents) => { if(Array.isArray(cents)) { return cents.map(e=>this.convert.cents_to_ratio(e)) } return Math.pow(2, cents / 1200) }, cents_to_simple_ratio: (cents,limit=17) => { if(Array.isArray(cents)) return cents.map(c=>this.convert.cents_to_simple_ratio(c,limit)) cents = this.mod(cents,1200) if(cents==0) { return { cents: 0, cents_in_octave: 0, value: 1, diff_in_octave: 0, ratio: '1/1', original: 0 } } let SR = this.get.simple_ratios(limit,true) let min for (let key of Object.keys(SR)) { if(min) { let diff_in_octave = Math.abs(SR[key].cents_in_octave-cents) let diff_min = Math.abs(SR[min].cents_in_octave-cents) if(diff_in_octave&lt;diff_min) min = key } else min = key } SR[min].diff_in_octave = cents-SR[min].cents_in_octave SR[min].ratio = min SR[min].original = cents return SR[min] }, /** Returns the midi_note and cents offset for a given pitch frequency in hertz * * @param {Number} hz - Some frequency of a pitch * @returns {Object} {midi: the midi-note number, cents: fine-tuning of note in cents} * @memberOf EDO#convert * @example * let edo = new EDO() * edo.convert.freq_to_midi(445) * //returns * { midi: 69, cents: 20 } * */ freq_to_midi: (hz) => { let result = (12*Math.log2(hz/440))+69 let midi_note = Math.floor(result) let dec = result-midi_note let cents = Math.round(dec*100) if(cents>50) { midi_note = midi_note+1 cents = (100-cents)*-1 } return {midi:midi_note, cents:cents} }, /** Returns a value in cents from a given interval * * @param {Number} interval - Some interval * @returns {Number} the interval represented in cents * @memberOf EDO#convert * @example * let edo = new EDO(17) // define a tuning with 17 divisions of the octave * edo.convert.interval_to_cents(6) * //returns 423.5294117647059*/ interval_to_cents: (interval) => { return this.cents_per_step * interval }, /** Returns a ratio as a decimal number from a given interval * * @param {Number|Array&lt;Number>} interval - Some interval * @returns {Number} a ratio * @memberOf EDO#convert * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.interval_to_ratio(7) * // returns 1.4983070768766815*/ interval_to_ratio: (interval) => { if(Array.isArray(interval)) return interval.map(i=>this.convert.interval_to_ratio(i)) return Math.pow(2, interval / this.edo) }, /** Given a list of intervals (or list of lists), returns pitches made with the intervals * starting from starting_pitch * @param {Array&lt;Number>|Array&lt;Array&lt;Number>>} intervals - a list of intervals * @param {Number} [starting_pitch=0] * @param {Boolean} [modulo] if modulo is provided, the pitches will conform to it * @returns {Array&lt;Number>|Array&lt;Array&lt;Number>>} The input as pitches * @memberOf EDO#convert * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.intervals_to_pitches([2,3]) * //returns [ 0, 2, 5 ]*/ intervals_to_pitches: (intervals, starting_pitch = 0, modulo = undefined) => { let pitches if (modulo) pitches = [mod(starting_pitch, modulo)] else pitches = [starting_pitch] for (let interval of intervals) { if (Array.isArray(interval)) { starting_pitch = pitches.flat()[pitches.flat().length - 1] let result = this.convert.intervals_to_pitches(interval, starting_pitch) result = result.slice(1) pitches.push(result) } else { if (modulo) pitches.push(mod(parseInt(pitches[pitches.length - 1]) + parseInt(interval)), modulo) else pitches.push(parseInt(pitches[pitches.length - 1]) + parseInt(interval)) } } return pitches }, /** &lt;p>Gets a series of intervallic units . Returns a scale as list of pitch classes&lt;/p> *&lt;p>Remark: "pitch classes" conform to the current tuning system used. 0-11 in 12EDO, 0-16 in 17EDO, etc.&lt;/p> * @param {Array&lt;Number>} intervals - A list of intervals * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.intervals_to_scale([2, 2, 1, 2, 2, 2, 1]) * // returns [0,2,4,5,7,9,11] * @returns {Number} A scale made up by adding the intervals in order * @memberOf EDO#convert*/ intervals_to_scale: (intervals) => { let pcs = [0] intervals.forEach((interval) => { pcs.push((interval + pcs[pcs.length - 1])) }) return this.scale(pcs,false).pitches }, /** Given a list of midi notes, returns a list of intervals * @param {Array&lt;Number>} midi - a list of midi pitches * @returns {Array&lt;Number>} The input as intervals * @memberOf EDO#convert * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.midi_to_intervals([60,64,57,61]) * //returns [ 4, -7, 4 ]*/ midi_to_intervals: (midi) => { let intervals = [] for (let i = 0; i &lt; midi.length - 1; i++) { intervals.push(midi[i + 1] - midi[i]) } return intervals }, /** Returns the name of the note (including octave) from a midi value * @param {Array&lt;Number>|Number} note_number - a midi note number or an array of midi note numbers * @param {Number} offset - an amount by which to shift note_number * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.midi_to_name([60,62]) * //returns ["C4","D4"] * @returns {Array&lt;String>|String} The input as note name(s) * @memberOf EDO#convert*/ midi_to_name: (note_number, offset = 0) => { /*Given a midi note code as an integer, returns its note name and octave disposition (e.g C4 for 60).*/ //only supports 12 edo, so it returns the input if in other edo if (this.edo != 12) return note_number //If it's an array of notes if (Array.isArray(note_number)) { return note_number.map((a) => this.convert.midi_to_name(a, offset)) } else { note_number = note_number + offset let octave = Math.floor(note_number / 12) - 1 let note_name = this.convert.pc_to_name(this.mod(note_number, 12)) return note_name.trim() + octave } }, /** Returns the frequency of the midi note * @param {Array&lt;Number>|Number} note_number - a midi note number or an array of midi note numbers * @param {Number} [offset=0] - By how much to offset every given number * @param {Number} [A=440] - What is the tuning of A * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.midi_to_freq(69) //returns 440 * edo.convert.midi_to_freq([69,70]) //returns [ 440, 466.1637615180899 ] * @returns {Array&lt;Number>|Number} the frequency of the midi note * @memberOf EDO#convert*/ midi_to_freq: (midi,offset=0,A=440) => { if(Array.isArray(midi)) return midi.map(n=>this.convert.midi_to_freq(n,offset,A)) else return Math.pow(2,((midi+offset)-69)/12)*A }, /** Gets a scale's name, and returns it as a Scale object * * @param {String} name - a scale's name (based on this API's naming formula) * @returns {Scale} a scale object * @memberOf EDO#convert * @example * let edo = new EDO(12) // define a tuning system * edo.convert.name_to_scale('12-1387') * //returns Scale object corresponding to the diatonic scale*/ name_to_scale: (name) => { name = name.split('-') let edo = name[0] name = name[1] if (edo != this.edo) return "Wrong edo" let vector = [] for (let i = edo; i > 0; i--) { let nw = Math.pow(2, i) if (nw > name) continue vector.push(i) name -= nw } vector.push(0) vector.reverse() return this.scale(vector, false) }, /** Returns the name of a note from a given pitch class (supports only 12-edo) * @param {Number | Array&lt;Number>} pc - a pitch class * @returns {String} The input as a note name * @memberOf EDO#convert * @example * let edo = new EDO(12) // define a tuning system with 12 divisions of the octave * edo.convert.pc_to_name(4) * //returns "E" * */ pc_to_name: (pc) => { let PC = { 0: 'C ', 1: 'C#', 2: 'D ', 3: 'Eb',