diff --git a/static/package.json b/static/package.json index 351cd87..6d6d8e0 100644 --- a/static/package.json +++ b/static/package.json @@ -11,23 +11,27 @@ "autoprefixer-loader": "^3.2.0", "babel-core": "^6.17.0", "babel-loader": "^6.2.5", + "babel-polyfill": "^6.20.0", "babel-preset-es2015": "^6.16.0", "buckets-js": "^1.98.1", "css-loader": "^0.23.1", "domready": "^1.0.8", "events": "^1.1.0", + "exports-loader": "^0.6.3", "file-loader": "^0.9.0", "jsmidgen": "^0.1.5", "midi-file-parser": "^1.0.0", + "midiconvert": "^0.4.1", "node-sass": "^3.4.2", "pepjs": "^0.4.2", "sass-loader": "^3.2.0", "startaudiocontext": "^1.2.0", "style-loader": "^0.13.1", - "three": "^0.81.2", - "tone": "^0.8.0", + "three": "^0.83.0", + "tone": "^0.9.0", "url-loader": "^0.5.7", "webmidi": "^2.0.0-beta.1", - "webpack": "^1.12.14" + "webpack": "^1.12.14", + "youtube-iframe": "^1.0.3" } } diff --git a/static/third_party/MidiConvert/LICENSE.md b/static/third_party/MidiConvert/LICENSE.md deleted file mode 100644 index c015913..0000000 --- a/static/third_party/MidiConvert/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -[The MIT License](http://opensource.org/licenses/MIT) - -Copyright © 2016 Yotam Mann - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/static/third_party/MidiConvert/README.md b/static/third_party/MidiConvert/README.md deleted file mode 100644 index 90380e7..0000000 --- a/static/third_party/MidiConvert/README.md +++ /dev/null @@ -1,112 +0,0 @@ -## [DEMO](https://tonejs.github.io/MidiConvert/) - -MidiConvert makes it straightforward to work with MIDI files in Javascript. It uses [midi-file-parser](https://github.com/NHQ/midi-file-parser) to decode MIDI files and [jsmidgen](https://github.com/dingram/jsmidgen) to encode MIDI files. - - -```javascript -//load a midi file -MidiConvert.load("path/to/midi.mid", function(midi){ - console.log(midi) -}) -``` - -### Format - -The data parsed from the midi file looks like this: - -```javascript -{ - // the transport and timing data - header : { - bpm : Number, // the tempo, e.g. 120 - timeSignature : [Number, Number], // the time signature, e.g. [4, 4], - PPQ : Number // the Pulses Per Quarter of the midi file - }, - // an array of midi tracks - tracks : [ - { - name : String, // the track name if one was given - notes : [ - { - midi : Number, // midi number, e.g. 60 - time : Number, // time in seconds - note : String, // note name, e.g. "C4" - velocity : Number, // normalized 0-1 velocity - duration : String // duration between noteOn and noteOff - } - ], - //midi control changes - controlChanges : { - //if there are control changes in the midi file - '91' : [ - { - number : Number // the cc number - time : Number, // time in seconds - value : Number // normalized 0-1 - } - ], - }, - instrument : String //the instrument if one is given - } - ] -} -``` - -### Raw Midi Parsing - -If you are using Node.js or have the raw binary string from the midi file, just use the `parse` method: - -```javascript -fs.readFile("test.mid", "binary", function(err, midiBlob){ - if (!err){ - var midi = MidiConvert.parse(midiBlob) - } -}) -``` - -### Encoding Midi - -You can also create midi files from scratch of by modifying an existing file. - -```javascript -//create a new midi file -var midi = MidiConvert.create() -//add a track -midi.track() - //chain note events: note, time, duration - .note(60, 0, 2) - .note(63, 1, 2) - .note(60, 2, 2) - -//write the output -fs.writeFileSync("output.mid", midi.encode(), "binary") -``` - -### Tone.Part - -The note data can be easily passed into [Tone.Part](http://tonejs.github.io/docs/#Part) - -```javascript -var synth = new Tone.PolySynth(8).toMaster() - -MidiConvert.load("path/to/midi.mid", function(midi){ - - //make sure you set the tempo before you schedule the events - Tone.Transport.bpm.value = midi.bpm - - //pass in the note events from one of the tracks as the second argument to Tone.Part - var midiPart = new Tone.Part(function(time, note){ - - //use the events to play the synth - synth.triggerAttackRelease(note.name, note.duration, time, note.velocity) - - }, midi.tracks[0].notes).start() - - //start the transport to hear the events - Tone.Transport.start() -}) -``` - -### Acknowledgment - -MidiConvert uses [midi-file-parser](https://github.com/NHQ/midi-file-parser) which is ported from [jasmid](https://github.com/gasman/jasmid) for decoding MIDI data and and [jsmidgen](https://github.com/dingram/jsmidgen) for encoding MIDI data. \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/BinaryInsert.js b/static/third_party/MidiConvert/src/BinaryInsert.js deleted file mode 100644 index 3debd6f..0000000 --- a/static/third_party/MidiConvert/src/BinaryInsert.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Return the index of the element at or before the given time - */ -function findElement(array, time) { - let beginning = 0 - const len = array.length - let end = len - if (len > 0 && array[len - 1].time <= time){ - return len - 1 - } - while (beginning < end){ - // calculate the midpoint for roughly equal partition - let midPoint = Math.floor(beginning + (end - beginning) / 2) - const event = array[midPoint] - const nextEvent = array[midPoint + 1] - if (event.time === time){ - //choose the last one that has the same time - for (let i = midPoint; i < array.length; i++){ - let testEvent = array[i] - if (testEvent.time === time){ - midPoint = i - } - } - return midPoint - } else if (event.time < time && nextEvent.time > time){ - return midPoint - } else if (event.time > time){ - //search lower - end = midPoint - } else if (event.time < time){ - //search upper - beginning = midPoint + 1 - } - } - return -1 -} - -/** - * Does a binary search to insert the note - * in the correct spot in the array - * @param {Array} array - * @param {Object} event - * @param {Number=} offset - */ -function BinaryInsert(array, event){ - if (array.length){ - const index = findElement(array, event.time) - array.splice(index + 1, 0, event) - } else { - array.push(event) - } -} - -export {BinaryInsert} \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/Control.js b/static/third_party/MidiConvert/src/Control.js deleted file mode 100644 index 4ad660a..0000000 --- a/static/third_party/MidiConvert/src/Control.js +++ /dev/null @@ -1,39 +0,0 @@ -const channelNames = { - "1" : "modulationWheel", - "2" : "breath", - "4" : "footController", - "5" : "portamentoTime", - "7" : "volume", - "8" : "balance", - "10" : "pan", - "64" : "sustain", - "65" : "portamentoTime", - "66" : "sostenuto", - "67" : "softPedal", - "68" : "legatoFootswitch", - "84" : "portamentoContro" -} - -class Control{ - constructor(number, time, value){ - - this.number = number - - this.time = time - - this.value = value - } - - /** - * The common name of the control change event - * @type {String} - * @readOnly - */ - get name(){ - if (channelNames.hasOwnProperty(this.number)){ - return channelNames[this.number] - } - } -} - -export {Control} \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/Header.js b/static/third_party/MidiConvert/src/Header.js deleted file mode 100644 index d95a635..0000000 --- a/static/third_party/MidiConvert/src/Header.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Parse tempo and time signature from the midiJson - * @param {Object} midiJson - * @return {Object} - */ -function parseHeader(midiJson){ - var ret = { - PPQ : midiJson.header.ticksPerBeat - } - for (var i = 0; i < midiJson.tracks.length; i++){ - var track = midiJson.tracks[i] - for (var j = 0; j < track.length; j++){ - var datum = track[j] - if (datum.type === "meta"){ - if (datum.subtype === "timeSignature"){ - ret.timeSignature = [datum.numerator, datum.denominator] - } else if (datum.subtype === "setTempo"){ - if (!ret.bpm){ - ret.bpm = 60000000 / datum.microsecondsPerBeat - } - } - } - } - } - ret.bpm = ret.bpm || 120 - return ret -} - -export {parseHeader} \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/Merge.js b/static/third_party/MidiConvert/src/Merge.js deleted file mode 100644 index 8ed2c62..0000000 --- a/static/third_party/MidiConvert/src/Merge.js +++ /dev/null @@ -1,44 +0,0 @@ - -function hasMoreValues(arrays, positions){ - for (let i = 0; i < arrays.length; i++){ - let arr = arrays[i] - let pos = positions[i] - if (arr.length > pos){ - return true - } - } - return false -} - -function getLowestAtPosition(arrays, positions, encoders){ - let lowestIndex = 0 - let lowestValue = Infinity - for (let i = 0; i < arrays.length; i++){ - let arr = arrays[i] - let pos = positions[i] - if (arr[pos] && (arr[pos].time < lowestValue)){ - lowestIndex = i - lowestValue = arr[pos].time - } - } - encoders[lowestIndex](arrays[lowestIndex][positions[lowestIndex]]) - // increment array - positions[lowestIndex] += 1 -} - -/** - * Combine multiple arrays keeping the timing in order - * The arguments should alternate between the array and the encoder callback - * @param {...Array|Function} args - */ -function Merge(...args){ - const arrays = args.filter((v, i) => (i % 2) === 0) - const positions = new Uint32Array(arrays.length) - const encoders = args.filter((v, i) => (i % 2) === 1) - const output = [] - while(hasMoreValues(arrays, positions)){ - getLowestAtPosition(arrays, positions, encoders) - } -} - -export {Merge} \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/Midi.js b/static/third_party/MidiConvert/src/Midi.js deleted file mode 100644 index d2ab97b..0000000 --- a/static/third_party/MidiConvert/src/Midi.js +++ /dev/null @@ -1,205 +0,0 @@ -import Decoder from 'midi-file-parser' -import Encoder from 'jsmidgen' -import Util from './Util' -import {Track} from './Track' -import {parseHeader} from './Header' - -/** - * @class The Midi object. Contains tracks and the header info. - */ -class Midi { - constructor(){ - - this.header = { - //defaults - bpm : 120, - timeSignature : [4, 4], - PPQ : 480 - } - - this.tracks = [] - } - - /** - * Load the given url and parse the midi at that url - * @param {String} url - * @param {*} data Anything that should be sent in the XHR - * @param {String} method Either GET or POST - * @return {Promise} - */ - load(url, data=null, method='GET'){ - return new Promise((success, fail) => { - var request = new XMLHttpRequest() - request.open(method, url) - request.responseType = 'arraybuffer' - // decode asynchronously - request.addEventListener('load', () => { - if (request.readyState === 4 && request.status === 200){ - success(this.decode(request.response)) - } else { - fail(request.status) - } - }) - request.addEventListener('error', fail) - request.send(data) - }) - } - - /** - * Decode the bytes - * @param {String|ArrayBuffer} bytes The midi file encoded as a string or ArrayBuffer - * @return {Midi} this - */ - decode(bytes){ - - if (bytes instanceof ArrayBuffer){ - var byteArray = new Uint8Array(bytes) - bytes = String.fromCharCode.apply(null, byteArray) - } - - const midiData = Decoder(bytes) - - this.header = parseHeader(midiData) - - //replace the previous tracks - this.tracks = [] - - midiData.tracks.forEach((trackData) => { - - const track = new Track() - this.tracks.push(track) - - let absoluteTime = 0 - trackData.forEach((event) => { - absoluteTime += Util.ticksToSeconds(event.deltaTime, this.header) - if (event.type === 'meta' && event.subtype === 'trackName'){ - track.name = Util.cleanName(event.text) - } else if (event.subtype === 'noteOn'){ - track.noteOn(event.noteNumber, absoluteTime, event.velocity / 127) - } else if (event.subtype === 'noteOff'){ - track.noteOff(event.noteNumber, absoluteTime) - } else if (event.subtype === 'controller' && event.controllerType){ - track.cc(event.controllerType, absoluteTime, event.value / 127) - } else if (event.type === 'meta' && event.subtype === 'instrumentName'){ - track.instrument = event.text - } - }) - }) - return this - } - - /** - * Encode the Midi object as a Buffer String - * @returns {String} - */ - encode(){ - const output = new Encoder.File({ - ticks : this.header.PPQ - }) - - this.tracks.forEach((track, i) => { - const trackEncoder = output.addTrack() - trackEncoder.setTempo(this.bpm) - track.encode(trackEncoder, this.header) - }) - return output.toBytes() - } - - /** - * Convert the output encoding into an Array - * @return {Array} - */ - toArray(){ - const encodedStr = this.encode() - const buffer = new Array(encodedStr.length) - for (let i = 0; i < encodedStr.length; i++){ - buffer[i] = encodedStr.charCodeAt(i) - } - return buffer - } - - /** - * Add a new track. - * @param {String=} name Optionally include the name of the track - * @returns {Track} - */ - track(name){ - const track = new Track(name) - this.tracks.push(track) - return track - } - - /** - * Get a track either by it's name or track index - * @param {Number|String} trackName - * @return {Track} - */ - get(trackName){ - if (Util.isNumber(trackName)){ - return this.tracks[trackName] - } else { - return this.tracks.find((t) => t.name === trackName) - } - } - - /** - * Slice the midi file between the startTime and endTime. Returns a copy of the - * midi - * @param {Number} startTime - * @param {Number} endTime - * @returns {Midi} this - */ - slice(startTime=0, endTime=this.duration){ - const midi = new Midi() - midi.header = this.header - midi.tracks = this.tracks.map((t) => t.slice(startTime, endTime)) - return midi - } - - /** - * the time of the first event - * @type {Number} - */ - get startTime(){ - const startTimes = this.tracks.map((t) => t.startTime) - return Math.min.apply(Math, startTimes) - } - - /** - * The bpm of the midi file in beats per minute - * @type {Number} - */ - get bpm(){ - return this.header.bpm - } - set bpm(bpm){ - const prevTempo = this.header.bpm - this.header.bpm = bpm - //adjust the timing of all the notes - const ratio = prevTempo / bpm - this.tracks.forEach((track) => track.scale(ratio)) - - } - - /** - * The timeSignature of the midi file - * @type {Array} - */ - get timeSignature(){ - return this.header.timeSignature - } - set timeSignature(timeSig){ - this.header.timeSignature = timeSignature - } - - /** - * The duration is the end time of the longest track - * @type {Number} - */ - get duration(){ - const durations = this.tracks.map((t) => t.duration) - return Math.max.apply(Math, durations) - } -} - -export {Midi} \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/MidiConvert.js b/static/third_party/MidiConvert/src/MidiConvert.js deleted file mode 100644 index 433ba26..0000000 --- a/static/third_party/MidiConvert/src/MidiConvert.js +++ /dev/null @@ -1,69 +0,0 @@ -import {Midi} from './Midi' - -const MidiConvert = { - /** - * Parse all the data from the Midi file into this format: - * { - * // the transport and timing data - * header : { - * bpm : Number, // tempo, e.g. 120 - * timeSignature : [Number, Number], // time signature, e.g. [4, 4], - * PPQ : Number // PPQ of the midi file - * }, - * // an array for each of the midi tracks - * tracks : [ - * { - * name : String, // the track name if one was given - * notes : [ - * { - * time : Number, // time in seconds - * name : String, // note name, e.g. 'C4' - * midi : Number, // midi number, e.g. 60 - * velocity : Number, // normalized velocity - * duration : Number // duration between noteOn and noteOff - * } - * ], - * controlChanges : { //all of the control changes - * 64 : [ //array for each cc value - * { - * number : Number, //the cc number - * time : Number, //the time of the event in seconds - * name : String, // if the cc value has a common name (e.g. 'sustain') - * value : Number, //the normalized value - * } - * ] - * } - * } - * ] - * } - * @param {Binary String} fileBlob The output from fs.readFile or FileReader - * @returns {Object} All of the options parsed from the midi file. - */ - parse : function(fileBlob){ - return new Midi().decode(fileBlob) - }, - /** - * Load and parse a midi file. See `parse` for what the results look like. - * @param {String} url - * @param {Function=} callback - * @returns {Promise} A promise which is invoked with the returned Midi object - */ - load : function(url, callback){ - const promise = new Midi().load(url) - if (callback){ - promise.then(callback) - } - return promise - }, - /** - * Create an empty midi file - * @return {Midi} - */ - create : function(){ - return new Midi() - } -} - -export default MidiConvert - -module.exports = MidiConvert diff --git a/static/third_party/MidiConvert/src/Note.js b/static/third_party/MidiConvert/src/Note.js deleted file mode 100644 index 7cca8b6..0000000 --- a/static/third_party/MidiConvert/src/Note.js +++ /dev/null @@ -1,100 +0,0 @@ -import Util from './Util' - -class Note{ - constructor(midi, time, duration=0, velocity=1){ - - /** - * The MIDI note number - * @type {Number} - */ - this.midi; - - if (Util.isNumber(midi)){ - this.midi = midi - } else if (Util.isPitch(midi)){ - this.name = midi - } else { - throw new Error('the midi value must either be in Pitch Notation (e.g. C#4) or a midi value') - } - - /** - * The note on time in seconds - * @type {Number} - */ - this.time = time - - /** - * The duration in seconds - * @type {Number} - */ - this.duration = duration - - /** - * The velocity 0-1 - * @type {Number} - */ - this.velocity = velocity - } - - /** - * If the note is the same as the given note - * @param {String|Number} note - * @return {Boolean} - */ - match(note){ - if (Util.isNumber(note)){ - return this.midi === note - } else if (Util.isPitch(note)){ - return this.name.toLowerCase() === note.toLowerCase() - } - } - - /** - * The note in Scientific Pitch Notation - * @type {String} - */ - get name(){ - return Util.midiToPitch(this.midi) - } - set name(name){ - this.midi = Util.pitchToMidi(name) - } - - /** - * Alias for time - * @type {Number} - */ - get noteOn(){ - return this.time - } - set noteOn(t){ - this.time = t - } - - /** - * The note off time - * @type {Number} - */ - get noteOff(){ - return this.time + this.duration - } - set noteOff(time){ - this.duration = time - this.time - } - - /** - * Convert the note to JSON - * @returns {Object} - */ - toJSON(){ - return { - name : this.name, - midi : this.midi, - time : this.time, - velocity : this.velocity, - duration : this.duration - } - } -} - -export {Note} \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/Track.js b/static/third_party/MidiConvert/src/Track.js deleted file mode 100644 index 6d2b5d8..0000000 --- a/static/third_party/MidiConvert/src/Track.js +++ /dev/null @@ -1,213 +0,0 @@ -import {Note} from './Note' -import {Control} from './Control' -import {Merge} from './Merge' -import {BinaryInsert} from './BinaryInsert' - -class Track { - constructor(name='', instrument=''){ - - /** - * The name of the track - * @type {String} - */ - this.name = name - - /** - * The note events - * @type {Array} - */ - this.notes = [] - - /** - * The control changes - * @type {Object} - */ - this.controlChanges = {} - - /** - * The tracks insturment if one exists - * @type {String} - */ - this.instrument = '' - } - - note(midi, time, duration=0, velocity=1){ - const note = new Note(midi, time, duration, velocity) - BinaryInsert(this.notes, note) - return this - } - - /** - * Add a note on event - * @param {Number|String} midi The midi note as either a midi number or - * Pitch Notation like ('C#4') - * @param {Number} time The time in seconds - * @param {Number} velocity The velocity value 0-1 - * @return {Track} this - */ - noteOn(midi, time, velocity=1){ - const note = new Note(midi, time, 0, velocity) - BinaryInsert(this.notes, note) - return this - } - - /** - * Add a note off event. Go through and find an unresolved - * noteOn event with the same pitch. - * @param {String|Number} midi The midi number or note name. - * @param {Number} time The time of the event in seconds - * @return {Track} this - */ - noteOff(midi, time){ - for (let i = 0; i < this.notes.length; i++){ - let note = this.notes[i] - if (note.match(midi) && note.duration === 0){ - note.noteOff = time - break; - } - } - return this - } - - /** - * Add a CC event - * @param {Number} num The CC number - * @param {Number} time The time of the event in seconds - * @param {Number} value The value of the CC - * @return {Track} this - */ - cc(num, time, value){ - if (!this.controlChanges.hasOwnProperty(num)){ - this.controlChanges[num] = [] - } - const cc = new Control(num, time, value) - BinaryInsert(this.controlChanges[num], cc) - return this - } - - /** - * An array of all the note on events - * @type {Array} - * @readOnly - */ - get noteOns(){ - const noteOns = [] - this.notes.forEach((note) => { - noteOns.push({ - time : note.noteOn, - midi : note.midi, - name : note.name, - velocity : note.velocity - }) - }) - return noteOns - } - - /** - * An array of all the noteOff events - * @type {Array} - * @readOnly - */ - get noteOffs(){ - const noteOffs = [] - this.notes.forEach((note) => { - noteOffs.push({ - time : note.noteOff, - midi : note.midi, - name : note.name - }) - }) - return noteOffs - } - - /** - * The length in seconds of the track - * @type {Number} - */ - get length() { - return this.notes.length - } - - /** - * The time of the first event in seconds - * @type {Number} - */ - get startTime() { - if (this.notes.length){ - let firstNote = this.notes[0] - return firstNote.noteOn - } else { - return 0 - } - } - - /** - * The time of the last event in seconds - * @type {Number} - */ - get duration() { - if (this.notes.length){ - let lastNote = this.notes[this.notes.length - 1] - return lastNote.noteOff - } else { - return 0 - } - } - - /** - * Scale the timing of all the events in the track - * @param {Number} amount The amount to scale all the values - */ - scale(amount){ - this.notes.forEach((note) => { - note.time *= amount - note.duration *= amount - }) - return this - } - - /** - * Slice returns a new track with only events that occured between startTime and endTime. - * Modifies this track. - * @param {Number} startTime - * @param {Number} endTime - * @returns {Track} - */ - slice(startTime=0, endTime=this.duration){ - // get the index before the startTime - const noteStartIndex = Math.max(this.notes.findIndex((note) => note.time >= startTime), 0) - const noteEndIndex = this.notes.findIndex((note) => note.noteOff >= endTime) + 1 - const track = new Track(this.name) - track.notes = this.notes.slice(noteStartIndex, noteEndIndex) - //shift the start time - track.notes.forEach((note) => note.time = note.time - startTime) - return track - } - - /** - * Write the output to the stream - */ - encode(trackEncoder, header){ - - const ticksPerSecond = header.PPQ / (60 / header.bpm) - let lastEventTime = 0 - - const CHANNEL = 0 - - function getDeltaTime(time){ - const ticks = Math.floor(ticksPerSecond * time) - const delta = Math.max(ticks - lastEventTime, 0) - lastEventTime = ticks - return delta - } - - Merge(this.noteOns, (noteOn) => { - trackEncoder.addNoteOn(CHANNEL, noteOn.name, getDeltaTime(noteOn.time), Math.floor(noteOn.velocity * 127)) - }, this.noteOffs, (noteOff) => { - trackEncoder.addNoteOff(CHANNEL, noteOff.name, getDeltaTime(noteOff.time)) - }) - } - -} - -export {Track} \ No newline at end of file diff --git a/static/third_party/MidiConvert/src/Util.js b/static/third_party/MidiConvert/src/Util.js deleted file mode 100644 index 3db37de..0000000 --- a/static/third_party/MidiConvert/src/Util.js +++ /dev/null @@ -1,53 +0,0 @@ -function cleanName(str){ - //ableton adds some weird stuff to the track - return str.replace(/\u0000/g, '') -} - -function ticksToSeconds(ticks, header){ - return (60 / header.bpm) * (ticks / header.PPQ); -} - -function isNumber(val){ - return typeof val === 'number' -} - -function isString(val){ - return typeof val === 'string' -} - -const isPitch = (function(){ - const regexp = /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i - return (val) => { - return isString(val) && regexp.test(val) - } -}()) - - -function midiToPitch(midi){ - const scaleIndexToNote = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; - const octave = Math.floor(midi / 12) - 1; - const note = midi % 12; - return scaleIndexToNote[note] + octave; -} - -const pitchToMidi = (function(){ - const regexp = /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i - const noteToScaleIndex = { - "cbb" : -2, "cb" : -1, "c" : 0, "c#" : 1, "cx" : 2, - "dbb" : 0, "db" : 1, "d" : 2, "d#" : 3, "dx" : 4, - "ebb" : 2, "eb" : 3, "e" : 4, "e#" : 5, "ex" : 6, - "fbb" : 3, "fb" : 4, "f" : 5, "f#" : 6, "fx" : 7, - "gbb" : 5, "gb" : 6, "g" : 7, "g#" : 8, "gx" : 9, - "abb" : 7, "ab" : 8, "a" : 9, "a#" : 10, "ax" : 11, - "bbb" : 9, "bb" : 10, "b" : 11, "b#" : 12, "bx" : 13, - } - return (note) => { - const split = regexp.exec(note) - const pitch = split[1] - const octave = split[2] - const index = noteToScaleIndex[pitch.toLowerCase()] - return index + (parseInt(octave) + 1) * 12 - } -}()) - -module.exports = {cleanName, ticksToSeconds, isString, isNumber, isPitch, midiToPitch, pitchToMidi} \ No newline at end of file