### Install Development Dependencies
Source: https://github.com/cuthbertlab/music21j/blob/master/README.md
Run these commands on first-time setup to install necessary development dependencies and browser binaries for testing.
```sh
$ npm install
$ npx playwright install chromium
```
--------------------------------
### Start Local Python Server and Run Demos
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/index.html
Navigate to the music21j directory, build the project with webpack, and start a Python server to view demos. Access the demos at http://localhost:8000/testHTML/.
```bash
% cd ~/git/music21j
% grunt webpack
% python start_python_server.py
```
--------------------------------
### Start Development Server
Source: https://github.com/cuthbertlab/music21j/blob/master/README.md
Use this command to start Vite's development server for local development with fast rebuilds and live reload. Navigate to http://localhost:5173/testHTML to view tests.
```sh
$ npm run dev
```
--------------------------------
### Install music21j via npm
Source: https://context7.com/cuthbertlab/music21j/llms.txt
Install the music21j library using npm. This command is for terminal usage.
```bash
npm install music21j
```
--------------------------------
### Install and Include music21j
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/renderTinyNotationDivs.html
To use TinyNotation rendering, install the music21j library via npm and include the debug script in your HTML. The second script tag is only needed if the divs already exist on the page.
```html
```
--------------------------------
### Keyboard Jazz Highlight Callback
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21.keyboard.html
An example of a callback function for jazz highlighting on a keyboard, intended for use with MIDI events. Requires prior setup of MIDI callbacks.
```javascript
var midiCallbacksPlay = [
music21.miditools.makeChords,
music21.miditools.sendToMIDIjs,
music21.keyboard.jazzHighlight.bind(k)
];
```
--------------------------------
### Create AudioBuffer from Buffers
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_audioRecording.js.html
Creates an AudioBuffer from provided audio data buffers. This is a setup step for playing back audio.
```javascript
playBuffers(buffers) {
const channels = 2;
const numFrames = buffers[0].length;
const audioBuffer = this.context.createBuffer(
channels,
numFrames,
this.context.sampleRate
);
```
--------------------------------
### Basic TinyNotation Example
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/renderTinyNotationDivs.html
Define a div with classes 'music21 tinyNotation' to display musical notation. Clicking the div will play the notation.
```html
c4 d8 e8 f2
(click me)
```
--------------------------------
### AbstractScale: Get Realization of Scale
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_scale.js.html
Calculates the pitches of a scale starting from a given pitch object. It caches the one-octave realization for efficiency. Handles string or Pitch object inputs for the starting pitch.
```javascript
getRealization(pitchObj, unused_stepOfPitch, unused_minPitch, unused_maxPitch, unused_direction, unused_reverse) {
// if (direction === undefined) {
// direction = DIRECTION_ASCENDING;
// }
// if (stepOfPitch === undefined) {
// stepOfPitch = 1;
// }
if (typeof pitchObj === 'string') {
pitchObj = new pitch.Pitch(pitchObj);
} else {
pitchObj = pitchObj.clone();
}
const post = [pitchObj];
for (const intV of this._net) {
pitchObj = intV.transposePitch(pitchObj);
post.push(pitchObj);
}
return post;
}
```
--------------------------------
### Keyboard Initialization and Configuration
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21.keyboard.html
Demonstrates the minimum usage and configuration options for the Keyboard class.
```APIDOC
## Minimum Usage
```javascript
const kd = document.getElementById('keyboardDiv');
const k = new music21.keyboard.Keyboard();
k.appendKeyboard(kd, 6, 57); // 88 key keyboard
```
## Configurable Properties
```javascript
// configurable:
k.scaleFactor = 1.2; // default 1
k.whiteKeyWidth = 40; // default 23
```
```
--------------------------------
### Start User Media Stream
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_audioSearch.js.html
Sets up the audio context, creates a MediaStreamSource, and connects an analyser node. This function patches Safari and requires some time to initialize.
```javascript
export function userMediaStarted(audioStream) {
/**
* This function which patches Safari requires some time to get started
* so we call it on object creation.
*/
config.sampleBuffer = new Float32Array(config.fftSize / 2);
const mediaStreamSource = config.audioContext.createMediaStreamSource(
audioStream
);
const analyser = config.audioContext.createAnalyser();
analyser.fftSize = config.fftSize;
mediaStreamSource.connect(analyser);
config.currentAnalyser = analyser;
animateLoop();
}
```
--------------------------------
### Get Element Sounding When Another Element Starts
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_stream.js.html
Retrieves the first element in the stream that is sounding when a given element begins. If multiple elements are sounding, it prioritizes elements of the same class as the input element, otherwise returning the first encountered.
```javascript
playingWhenAttacked(el, elStream) {
let elOffset;
if (elStream !== undefined) {
elOffset = el.getOffsetBySite(elStream);
} else {
elOffset = el.offset;
}
const otherElements = this.getElementsByOffset(elOffset, elOffset, { mustBeginInSpan: false });
if (otherElements.length === 0) {
return undefined;
} else if (otherElements.length === 1) {
return otherElements.get(0);
} else {
for (const thisEl of otherElements) {
if (el.constructor === thisEl.constructor) {
return thisEl;
}
}
return otherElements.get(0);
}
}
```
--------------------------------
### Main Function for Setup
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/colorChanger.html
Initializes a music21 stream with notes, sets key and time signatures, and appends the stream's DOM representation to the page. Also demonstrates appending a Roman numeral chord.
```javascript
function main() {
s = undefined;
const k = new music21.key.Key('D');
s = new music21.stream.Measure();
s.keySignature = k;
s.timeSignature = new music21.meter.TimeSignature('4/4');
const n = new music21.note.Note('G4');
n.duration.type = 'half';
s.append(n);
const n2 = new music21.note.Note('A4');
s.append(n2);
const n3 = new music21.note.Note('B4');
s.append(n3);
s.autoBeam = false;
const d = getColorDOM(s);
document.querySelector('#SVGDiv')
.appendChild(d);
const sChord = new music21.stream.Measure();
sChord.timeSignature = new music21.meter.TimeSignature('4/4');
const ch = new music21.roman.RomanNumeral('IV', k);
ch.duration.type = 'whole';
sChord.keySignature = k;
sChord.append(ch);
sChord.appendNewDOM(document.querySelector('#SVGDiv'));
}
```
--------------------------------
### Note Start Setter for Interval
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_interval.js.html
Sets the starting note of the interval and automatically calculates and sets the ending note by transposing the starting note's pitch.
```javascript
set noteStart(n) {
this._noteStart = n;
const p1 = n.pitch;
const p2 = this.transposePitch(p1);
this._noteEnd = n.clone();
this._noteEnd.pitch = p2;
}
```
--------------------------------
### Initialize and Connect Audio Source
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_audioRecording.js.html
Sets up the audio context, creates a Web Worker for asynchronous audio processing, and connects the source to the processing node and audio destination. This is essential for enabling recording functionality.
```javascript
const zeroGain = this.audioContext.createGain();
zeroGain.gain.value = 0.0;
inputPoint.connect(zeroGain);
zeroGain.connect(this.audioContext.destination);
}
/
* Creates a worker to receive and process all the messages asynchronously.
*
* @param {GainNode} source;
*/
connectSource(source) {
/
*
* @type {BaseAudioContext}
*/
const context = source.context;
this.context = context;
this.setNode();
// create a Worker with inline code...
const workerBlob = new Blob(['(', recorderWorkerJs, ')()'], {
type: 'application/javascript',
});
const workerURL = URL.createObjectURL(workerBlob);
this.worker = new Worker(workerURL);
/**
* When worker sends a message, we just send it to the currentCallback...
*/
this.worker.onmessage = e => {
const blob = e.data;
this.currCallback(blob);
};
URL.revokeObjectURL(workerURL);
this.worker.postMessage({
command: 'init',
config: {
sampleRate: this.context.sampleRate,
},
});
/**
* Whenever the ScriptProcessorNode receives enough audio to process
* (i.e., this.bufferLen stereo samples; default 4096), then it calls onaudioprocess
* which is set up to send the event's .getChannelData to the WebWorker via a
* postMessage.
*
* The 'record' command sends no message back.
*/
this.node.onaudioprocess = e => {
if (!this.recording) {
return;
}
this.worker.postMessage({
command: 'record',
buffer: [
e.inputBuffer.getChannelData(0),
e.inputBuffer.getChannelData(1),
],
});
};
source.connect(this.node);
/**
* polyfill for Chrome error.
*
* if the ScriptProcessorNode (this.node) is not connected to an output
* the "onaudioprocess" event is not triggered in Chrome.
*/
this.node.connect(this.context.destination);
}
```
--------------------------------
### Install Music21j in a JavaScript/TypeScript Project
Source: https://github.com/cuthbertlab/music21j/blob/master/README.md
Install music21j as a dependency for your JavaScript or TypeScript project using npm.
```bash
$ npm install --save music21j
```
--------------------------------
### Setup Download Link
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_audioRecording.js.html
Creates a downloadable link for a given Blob object. It generates a URL for the blob and sets the href and download attributes of a specified HTML element.
```javascript
setupDownload(blob, filename, elementId) {
elementId = elementId || 'save';
const url = (window.URL || window.webkitURL).createObjectURL(blob);
const link = document.getElementById(elementId);
link.href = url;
link.download = filename || 'output.wav';
}
```
--------------------------------
### Get Stem Direction from Clef
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_note.js.html
Placeholder method to get stem direction from a clef. Returns undefined.
```javascript
getStemDirectionFromClef(clef) {
return undefined;
}
```
--------------------------------
### Get Length of Beams List in music21j
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_beam.js.html
Accessor property to get the number of beams currently in the beamsList.
```javascript
get length() {
return this.beamsList.length;
}
```
--------------------------------
### Code Highlighting Setup
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_tempo.js.html
Configures code blocks within tutorial and readme sections for syntax highlighting using Sunlight. It adds specific classes for highlighting and line numbers, and then calls Sunlight.highlightAll() to process all highlighted code.
```javascript
$( ".tutorial-section pre, .readme-section pre" ).each( function () {
var $this = $( this );
var example = $this.find( "code" );
exampleText = example.html();
var lang = /{@lang (.*?)}/.exec( exampleText );
if ( lang && lang[1] ) {
exampleText = exampleText.replace( lang[0], "" );
example.html( exampleText );
lang = lang[1];
} else {
lang = "javascript";
}
if ( lang ) {
$this
.addClass( "sunlight-highlight-" + lang )
.addClass( "linenums" )
.html( example.html() );
}
} );
Sunlight.highlightAll( {
lineNumbers : true,
showMenu : true,
enableDoclinks : true
} );
```
--------------------------------
### Start Note Sequence Interval
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/demo-Cuthbert.html
This function starts an interval timer to repeatedly call playSeventy, initiating the sequence of notes.
```javascript
function refreshMe() {
stopIntervalId = setInterval(playSeventy, 100);
}
```
--------------------------------
### Create and Configure Keyboard
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21.keyboard.html
Demonstrates the minimum usage for creating a keyboard instance and appending it to a DOM element. Configuration options for scaleFactor and whiteKeyWidth are also shown.
```javascript
const kd = document.getElementById('keyboardDiv');
const k = new music21.keyboard.Keyboard();
k.appendKeyboard(kd, 6, 57); // 88 key keyboard
// configurable:
k.scaleFactor = 1.2; // default 1
k.whiteKeyWidth = 40; // default 23
```
--------------------------------
### Build music21j Project
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/index.html
Use this command to build the music21j project.
```bash
$ grunt webpack
```
--------------------------------
### Get VexFlow Duration String
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_duration.js.html
Illustrates how to get the VexFlow-compatible duration string from a Duration object. Dots are appended to the base type string.
```javascript
var d = new music21.duration.Duration(2);
d.vexflowDuration == 'h'; // true;
d.dots = 2;
d.vexflowDuration == 'hdd'; // true;
```
--------------------------------
### Build Documentation
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/index.html
Command to build the project's documentation using JSDoc.
```bash
grunt jsdoc
```
--------------------------------
### Create MusicXML Tie Elements
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_musicxml_m21ToXml.js.html
Generates MusicXML 'tie' elements based on the type of tie (start or stop). Handles 'continue' ties by creating both a 'stop' and a 'start' tie.
```javascript
if (t.type === 'continue') {
musicxmlTieType = 'stop';
}
const mxTie = this.doc.createElement('tie');
mxTie.setAttribute('type', musicxmlTieType);
mxTieList.push(mxTie);
if (t.type === 'continue') {
const mxTie = this.doc.createElement('tie');
mxTie.setAttribute('type', 'start');
mxTieList.push(mxTie);
}
return mxTieList;
}
```
--------------------------------
### Run Music21j Configuration
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_parseLoader.js.html
Initializes music21j by loading configuration from window or a JSON attribute, setting up paths, and rendering HTML elements. It handles soundfont loading and HTML rendering based on configuration.
```javascript
export function runConfiguration() {
let conf;
// noinspection JSUnresolvedVariable
if (typeof window.m21conf !== 'undefined') {
// noinspection JSUnresolvedVariable
conf = window.m21conf;
} else {
conf = loadConfiguration();
}
conf.warnBanner = (conf.warnBanner !== undefined) ? conf.warnBanner : warnBanner();
conf.loadSoundfont = (conf.loadSoundfont !== undefined) ? conf.loadSoundfont : getM21attribute('loadSoundFont') || true;
conf.renderHTML = (conf.renderHTML !== undefined) ? conf.renderHTML : getM21attribute('renderHTML');
if (conf.renderHTML === undefined) {
conf.renderHTML = true;
}
conf.m21basePath = getBasePath();
fixUrls(conf);
loadDefaultSoundfont(conf);
renderHTML();
}
```
--------------------------------
### Multiple Midi Players on a Page
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/embedPlayer.html
This example demonstrates how to instantiate and manage multiple MIDI players on the same HTML page. Each player can be configured independently to play different MIDI files.
```javascript
// noinspection SpellCheckingInspection song = [
// Sinding - Rustles of Spring Op-32 No-3
'data:audio/midi;base64,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
```
--------------------------------
### Basic webmidi usage with MIDI input selector
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21.module_webmidi.html
This example demonstrates the smallest usage of the webmidi toolkit. It requires jQuery and the music21/miditools module. The code sets up a MIDI input selector and defines a callback function to process incoming MIDI events, displaying them as music21 notes.
```html
MIDI In/Jazz Test for Music21j
```
--------------------------------
### Python to Javascript Conversion Example
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_fromPython.js.html
This example demonstrates the typical workflow for converting a Python-encoded music21 stream to a music21j object. First, freeze the stream in Python, then load it in Javascript using the Converter.
```python
s = corpus.parse('bwv66.6')
stringRepresentingM21JsonPickle = s.freezeStream('jsonpickle')
```
```javascript
pyConv = new music21.fromPython.Converter();
s = pyConv.run(stringRepresentingM21JsonPickle);
```
--------------------------------
### Build Project
Source: https://github.com/cuthbertlab/music21j/blob/master/README.md
Run this command to produce the UMD bundle (build/music21.debug.js) and sourcemaps, suitable for browser use or npm publishing.
```sh
$ npm run build
```
--------------------------------
### Generate Numeric Range in JavaScript
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_common.js.html
Creates an array of numbers within a specified range. Supports start, stop, and step values. If only one argument is provided, it is treated as the stop value with a start of 0 and a step of 1.
```javascript
export function range(start, stop, step) {
if (step === undefined) {
step = 1;
}
if (stop === undefined) {
stop = start;
start = 0;
}
const count = Math.ceil((stop - start) / step);
return Array.apply(0, Array(count)).map((e, i) => i * step + start);
}
```
--------------------------------
### Initialize MIDI Input and Metronome
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/midiInChords.html
Sets up the music21 stream, metronome, and MIDI input callbacks. Requires a MIDI keyboard and Jazz Plugin.
```javascript
let s;
let metro;
function appendElement(appendObject) {
if (s.length > 7) {
s.elements = s.elements.slice(1)
}
s.append(appendObject);
const svgDiv = document.querySelector("#svgDiv");
svgDiv.replaceChildren();
s.appendNewDOM(svgDiv);
}
function main() {
s = new music21.stream.Measure();
s.clef = new music21.clef.TrebleClef();
s.renderOptions.staffLines = 5;
metro = new music21.tempo.Metronome();
metro.addDiv(document.querySelector("#metronomeDiv"));
music21.miditools.config.metronome = metro;
music21.webmidi.createSelector(document.querySelector("#putMidiSelectHere"));
music21.miditools.callbacks.general = [
music21.miditools.makeChords,
music21.miditools.sendToMIDIjs,
];
music21.miditools.callbacks.sendOutChord = appendElement;
}
document.addEventListener('DOMContentLoaded', () => {
main();
});
```
--------------------------------
### MIDI Input Setup with Custom Failure Handler
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/midiInChordsCustomFail.html
Configures MIDI input to create chords and handle access failures with a custom alert message. Requires a MIDI keyboard and the Jazz Plugin.
```javascript
let s;
let metro;
function appendElement(appendObject) {
if (s.length > 7) {
s.elements = s.elements.slice(1)
}
s.append(appendObject);
const svgDiv = document.querySelector("#svgDiv");
svgDiv.replaceChildren();
s.appendNewDOM(svgDiv);
}
function main() {
s = new music21.stream.Measure();
s.clef = new music21.clef.TrebleClef();
s.renderOptions.staffLines = 5;
metro = new music21.tempo.Metronome();
metro.addDiv(document.querySelector("#metronomeDiv"));
music21.miditools.config.metronome = metro;
music21.webmidi.createSelector(
document.querySelector("#putMidiSelectHere"),
{onAccessFailure: e => {
alert(e.message + '(' + e.name + ')')
}}
);
music21.miditools.callbacks.general = [
music21.miditools.makeChords,
music21.miditools.sendToMIDIjs,
];
music21.miditools.callbacks.sendOutChord = appendElement;
}
document.addEventListener('DOMContentLoaded', () => {
main();
});
```
--------------------------------
### Set Measure Start Attributes
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_musicxml_m21ToXml.js.html
Creates and appends MusicXML 'attributes' for the start of a measure, including divisions, key signature, time signature, and clef if they differ from the parent or are defined. Appends to the XML root only if new attributes are added.
```javascript
setMxAttributesObjectForStartOfMeasure() {
const m = this.stream;
const mxAttributes = this.doc.createElement('attributes');
let appendToRoot = false;
this.currentDivisions = divisionsPerQuarter;
if (this.parent === undefined || this.currentDivisions !== this.parent.lastDivisions) {
const mxDivisions = this.subElement(mxAttributes, 'divisions');
mxDivisions.innerHTML = this.currentDivisions.toString();
this.parent.lastDivisions = this.currentDivisions;
appendToRoot = true;
}
if (m.classes.includes('Measure')) {
if (m._keySignature !== undefined) {
mxAttributes.appendChild(this.keySignatureToXml(m._keySignature));
appendToRoot = true;
}
if (m._timeSignature !== undefined) {
mxAttributes.appendChild(this.timeSignatureToXml(m._timeSignature));
appendToRoot = true;
}
// todo SenzaMisura...
if (m._clef !== undefined) {
mxAttributes.appendChild(this.clefToXml(m._clef));
appendToRoot = true;
}
}
// staffLayout
// transpositionInterval
// measureStyle
if (appendToRoot) {
this.xmlRoot.appendChild(mxAttributes);
}
return mxAttributes;
}
```
--------------------------------
### duration Getter/Setter
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_stream.js.html
Gets or sets the duration of the stream.
```APIDOC
## duration Getter/Setter
### Description
Manages the overall duration of the stream.
### Getter
`get duration()`
- **Returns**: A `duration.Duration` object representing the stream's duration. If not explicitly set, it's derived from the `highestTime`.
### Setter
`set duration(newDuration)`
- **Parameters**:
- **newDuration** (duration.Duration) - The new duration to set for the stream.
```
--------------------------------
### Initialize and Load MIDI File
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_miditools.js.html
Initializes the MIDI player, sets playback speed, loads a soundfont, and then loads a base64 encoded MIDI file. Includes callbacks for successful loading and failure.
```javascript
const player = this.player;
player.timeWarp = this.speed;
const m21MidiPlayer = this;
loadSoundfont('acoustic_grand_piano', () => {
player.loadFile(
b64data,
() => {
// success
m21MidiPlayer.fileLoaded();
},
undefined, // loading
e => {
// failure
console.log(e);
}
);
});
```
--------------------------------
### StreamIterator: Get Voices
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_stream_iterator.js.html
Adds a filter to select only 'Voice' elements.
```javascript
get voices() {
return this.addFilter(new filters.ClassFilter('Voice'));
}
```
--------------------------------
### Initialize MIDI Input and Keyboard Handling
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/midiInKeyChords.html
Sets up the music21 stream, metronome, and keyboard. Configures MIDI input callbacks to process incoming notes as chords and highlight them on a virtual keyboard. Ensure WebMIDI is enabled in Chrome or use the Jazz plugin.
```javascript
let s;
let metro;
function appendElement(appendObject) {
if (s.length > 7) {
s.elements = s.elements.slice(1)
}
s.append(appendObject);
const svgDiv = document.querySelector("#svgDiv");
svgDiv.replaceChildren();
s.appendNewDOM(svgDiv);
}
function main() {
s = new music21.stream.Measure();
s.clef = new music21.clef.TrebleClef();
s.renderOptions.staffLines = 5;
metro = new music21.tempo.Metronome();
metro.addDiv(document.querySelector("#metronomeDiv"));
music21.miditools.config.metronome = metro;
const k = new music21.keyboard.Keyboard();
const kd = document.getElementById('keyboardDiv');
k.startPitch = 18; // 6
k.endPitch = 39; // 57
k.appendKeyboard(kd); // 37key keyboard
music21.webmidi.createSelector(document.querySelector("#putMidiSelectHere"));
music21.miditools.callbacks.general = [
music21.miditools.makeChords,
music21.keyboard.jazzHighlight.bind(k),
music21.miditools.sendToMIDIjs,
];
music21.miditools.callbacks.sendOutChord = appendElement;
}
document.addEventListener('DOMContentLoaded', () => {
main();
});
```
--------------------------------
### StreamIterator: Get Spanners
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_stream_iterator.js.html
Adds a filter to select only 'Spanner' elements.
```javascript
get spanners() {
return this.addFilter(new filters.ClassFilter('Spanner'));
}
```
--------------------------------
### Initialize Audio Recording
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_audioRecording.js.html
Initializes the audio recording system by polyfilling navigator and requesting microphone access. This method should be called to start the audio input process.
```javascript
initAudio() {
this.polyfillNavigator();
// not sure what function signature this wants.
// noinspection JSCheckFunctionSignatures
navigator.getUserMedia(
{
audio: {
mandatory: {
googEchoCancellation: 'false',
googAutoGainControl: 'false',
googNoiseSuppression: 'false',
googHighpassFilter: 'false',
// 'echoCancellation': false,
// 'autoGainControl': false,
// 'noiseSuppression': false,
// 'highpassFilter': false,
},
optional: [],
},
},
s => this.audioStreamConnected(s),
error => {
console.log('Error getting audio -- try on google Chrome?');
console.log(error);
}
);
}
```
--------------------------------
### StreamIterator: Get Parts
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_stream_iterator.js.html
Adds a filter to select only 'Part' elements.
```javascript
get parts() {
return this.addFilter(new filters.ClassFilter('Part'));
}
```
--------------------------------
### exports.MusicOrdinals
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21.interval.html
An array containing ordinal names for musical terms, starting from Unison.
```APIDOC
## exports.MusicOrdinals
### Description
An array containing ordinal names for musical terms, such as Unison, Second, Third, etc.
### Example
```javascript
for (var i = 1; i < music21.interval.MusicOrdinals.length; i++) {
console.log(i, music21.interval.MusicOrdinals[i]);
}
// Output:
// 1, Unison
// 2, Second
// 3, Third
// ...
// 8, Octave
// ...
// 15, Double Octave
```
```
--------------------------------
### prepareFlat
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_vfShow.js.html
Main internal routine to prepare a flat stream.
```APIDOC
## prepareFlat
### Description
Main internal routine to prepare a flat stream.
### Method
prepareFlat(s, stack, optionalStave, optional_renderOp)
### Parameters
#### Path Parameters
- **s** (music21.stream.Stream) - A flat stream object.
- **stack** (music21.vfShow.RenderStack) - A RenderStack object to prepare into.
- **optionalStave** (Vex.Flow.Stave) - An optional existing stave.
- **optional_renderOp** (Object) - Render options. Passed to {@link music21.vfShow.Renderer#renderStave}
### Returns
- **stave** (Vex.Flow.Stave) - The staff to return. (also changes the `stack` parameter and runs `makeNotation` on s)
```
--------------------------------
### Main Initialization Function
Source: https://github.com/cuthbertlab/music21j/blob/master/testHTML/showKeyboard.html
Sets up the main music21j objects including Parts, Measures, a Score, and a Metronome. It configures rendering options, inserts clefs, and initializes the keyboard and MIDI callbacks. Also sets up the event listener for switching between single and grand staff views.
```javascript
function main() {
p = new music21.stream.Part();
m = new music21.stream.Measure();
p.insert(0, m);
m.clef = new music21.clef.TrebleClef();
p.renderOptions.scaleFactor = { x: 1.5, y: 1.5 };
p1 = new music21.stream.Part();
m1 = new music21.stream.Measure();
p1.insert(0, m1);
m1.clef = new music21.clef.TrebleClef();
p2 = new music21.stream.Part();
m2 = new music21.stream.Measure();
p2.insert(0, m2);
m2.clef = new music21.clef.BassClef();
sc = new music21.stream.Score();
sc.insert(0, p1);
sc.insert(0, p2);
sc.partSpacing = 90;
sc.renderOptions.scaleFactor = { x: 1.5, y: 1.5 };
metro = new music21.tempo.Metronome();
metro.addDiv(document.querySelector("#metronomeDiv"));
music21.miditools.config.metronome = metro;
music21.miditools.config.maxDelay = 200;
music21.webmidi.createSelector(document.querySelector("#putMidiSelectHere"));
const staffRadio = document.querySelector('input[type=radio][name=staffNumberSelector]')
staffRadio.addEventListener('change', e => {
if (e.target.value === 'singleStaff') {
document.querySelector("#svgDiv").style.display = 'block';
document.querySelector("#svgDivGrandStaff").style.display = 'none';
music21.miditools.callbacks.sendOutChord = appendElement;
} else if (e.target.value === 'grandStaff') {
document.querySelector("#svgDiv").style.display = 'none';
document.querySelector("#svgDivGrandStaff").style.displ
}
});
}
```
--------------------------------
### Enharmonic Equivalents
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_pitch.js.html
Methods for getting higher and lower enharmonic equivalents of a pitch.
```APIDOC
## Enharmonic Equivalents
### Description
Provides methods to get the higher or lower enharmonic equivalent of a pitch.
### Methods
- `getHigherEnharmonic(inPlace=false)`: Returns the higher enharmonic equivalent. If `inPlace` is true, modifies the current pitch.
- `getLowerEnharmonic(inPlace=false)`: Returns the lower enharmonic equivalent. If `inPlace` is true, modifies the current pitch.
### Parameters
- `inPlace` (boolean): Optional. If true, modifies the current pitch object. Defaults to false.
```
--------------------------------
### StreamIterator: Get Notes
Source: https://github.com/cuthbertlab/music21j/blob/master/doc/music21_stream_iterator.js.html
Adds a filter to select only note elements, excluding rests.
```javascript
get notes() {
return this.addFilter(new filters.ClassFilter('NotRest'));
}
```