1(function() { 2 "use strict"; 3 var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}; 4 function getAugmentedNamespace(n) { 5 if (n.__esModule) return n; 6 var f = n.default; 7 if (typeof f == "function") { 8 var a = function a2() { 9 if (this instanceof a2) { 10 return Reflect.construct(f, arguments, this.constructor); 11 } 12 return f.apply(this, arguments); 13 }; 14 a.prototype = f.prototype; 15 } else a = {}; 16 Object.defineProperty(a, "__esModule", { value: true }); 17 Object.keys(n).forEach(function(k) { 18 var d = Object.getOwnPropertyDescriptor(n, k); 19 Object.defineProperty(a, k, d.get ? d : { 20 enumerable: true, 21 get: function() { 22 return n[k]; 23 } 24 }); 25 }); 26 return a; 27 } 28 var Midi = {}; 29 var midiFile = {}; 30 function parseMidi(data) { 31 var p = new Parser(data); 32 var headerChunk = p.readChunk(); 33 if (headerChunk.id != "MThd") 34 throw "Bad MIDI file. Expected 'MHdr', got: '" + headerChunk.id + "'"; 35 var header = parseHeader(headerChunk.data); 36 var tracks = []; 37 for (var i = 0; !p.eof() && i < header.numTracks; i++) { 38 var trackChunk = p.readChunk(); 39 if (trackChunk.id != "MTrk") 40 throw "Bad MIDI file. Expected 'MTrk', got: '" + trackChunk.id + "'"; 41 var track = parseTrack(trackChunk.data); 42 tracks.push(track); 43 } 44 return { 45 header, 46 tracks 47 }; 48 } 49 function parseHeader(data) { 50 var p = new Parser(data); 51 var format = p.readUInt16(); 52 var numTracks = p.readUInt16(); 53 var result = { 54 format, 55 numTracks 56 }; 57 var timeDivision = p.readUInt16(); 58 if (timeDivision & 32768) { 59 result.framesPerSecond = 256 - (timeDivision >> 8); 60 result.ticksPerFrame = timeDivision & 255; 61 } else { 62 result.ticksPerBeat = timeDivision; 63 } 64 return result; 65 } 66 function parseTrack(data) { 67 var p = new Parser(data); 68 var events = []; 69 while (!p.eof()) { 70 var event = readEvent(); 71 events.push(event); 72 } 73 return events; 74 var lastEventTypeByte = null; 75 function readEvent() { 76 var event2 = {}; 77 event2.deltaTime = p.readVarInt(); 78 var eventTypeByte = p.readUInt8(); 79 if ((eventTypeByte & 240) === 240) { 80 if (eventTypeByte === 255) { 81 event2.meta = true; 82 var metatypeByte = p.readUInt8(); 83 var length = p.readVarInt(); 84 switch (metatypeByte) { 85 case 0: 86 event2.type = "sequenceNumber"; 87 if (length !== 2) throw "Expected length for sequenceNumber event is 2, got " + length; 88 event2.number = p.readUInt16(); 89 return event2; 90 case 1: 91 event2.type = "text"; 92 event2.text = p.readString(length); 93 return event2; 94 case 2: 95 event2.type = "copyrightNotice"; 96 event2.text = p.readString(length); 97 return event2; 98 case 3: 99 event2.type = "trackName"; 100 event2.text = p.readString(length); 101 return event2; 102 case 4: 103 event2.type = "instrumentName"; 104 event2.text = p.readString(length); 105 return event2; 106 case 5: 107 event2.type = "lyrics"; 108 event2.text = p.readString(length); 109 return event2; 110 case 6: 111 event2.type = "marker"; 112 event2.text = p.readString(length); 113 return event2; 114 case 7: 115 event2.type = "cuePoint"; 116 event2.text = p.readString(length); 117 return event2; 118 case 32: 119 event2.type = "channelPrefix"; 120 if (length != 1) throw "Expected length for channelPrefix event is 1, got " + length; 121 event2.channel = p.readUInt8(); 122 return event2; 123 case 33: 124 event2.type = "portPrefix"; 125 if (length != 1) throw "Expected length for portPrefix event is 1, got " + length; 126 event2.port = p.readUInt8(); 127 return event2; 128 case 47: 129 event2.type = "endOfTrack"; 130 if (length != 0) throw "Expected length for endOfTrack event is 0, got " + length; 131 return event2; 132 case 81: 133 event2.type = "setTempo"; 134 if (length != 3) throw "Expected length for setTempo event is 3, got " + length; 135 event2.microsecondsPerBeat = p.readUInt24(); 136 return event2; 137 case 84: 138 event2.type = "smpteOffset"; 139 if (length != 5) throw "Expected length for smpteOffset event is 5, got " + length; 140 var hourByte = p.readUInt8(); 141 var FRAME_RATES = { 0: 24, 32: 25, 64: 29, 96: 30 }; 142 event2.frameRate = FRAME_RATES[hourByte & 96]; 143 event2.hour = hourByte & 31; 144 event2.min = p.readUInt8(); 145 event2.sec = p.readUInt8(); 146 event2.frame = p.readUInt8(); 147 event2.subFrame = p.readUInt8(); 148 return event2; 149 case 88: 150 event2.type = "timeSignature"; 151 if (length != 2 && length != 4) throw "Expected length for timeSignature event is 4 or 2, got " + length; 152 event2.numerator = p.readUInt8(); 153 event2.denominator = 1 << p.readUInt8(); 154 if (length === 4) { 155 event2.metronome = p.readUInt8(); 156 event2.thirtyseconds = p.readUInt8(); 157 } else { 158 event2.metronome = 36; 159 event2.thirtyseconds = 8; 160 } 161 return event2; 162 case 89: 163 event2.type = "keySignature"; 164 if (length != 2) throw "Expected length for keySignature event is 2, got " + length; 165 event2.key = p.readInt8(); 166 event2.scale = p.readUInt8(); 167 return event2; 168 case 127: 169 event2.type = "sequencerSpecific"; 170 event2.data = p.readBytes(length); 171 return event2; 172 default: 173 event2.type = "unknownMeta"; 174 event2.data = p.readBytes(length); 175 event2.metatypeByte = metatypeByte; 176 return event2; 177 } 178 } else if (eventTypeByte == 240) { 179 event2.type = "sysEx"; 180 var length = p.readVarInt(); 181 event2.data = p.readBytes(length); 182 return event2; 183 } else if (eventTypeByte == 247) { 184 event2.type = "endSysEx"; 185 var length = p.readVarInt(); 186 event2.data = p.readBytes(length); 187 return event2; 188 } else { 189 throw "Unrecognised MIDI event type byte: " + eventTypeByte; 190 } 191 } else { 192 var param1; 193 if ((eventTypeByte & 128) === 0) { 194 if (lastEventTypeByte === null) 195 throw "Running status byte encountered before status byte"; 196 param1 = eventTypeByte; 197 eventTypeByte = lastEventTypeByte; 198 event2.running = true; 199 } else { 200 param1 = p.readUInt8(); 201 lastEventTypeByte = eventTypeByte; 202 } 203 var eventType = eventTypeByte >> 4; 204 event2.channel = eventTypeByte & 15; 205 switch (eventType) { 206 case 8: 207 event2.type = "noteOff"; 208 event2.noteNumber = param1; 209 event2.velocity = p.readUInt8(); 210 return event2; 211 case 9: 212 var velocity = p.readUInt8(); 213 event2.type = velocity === 0 ? "noteOff" : "noteOn"; 214 event2.noteNumber = param1; 215 event2.velocity = velocity; 216 if (velocity === 0) event2.byte9 = true; 217 return event2; 218 case 10: 219 event2.type = "noteAftertouch"; 220 event2.noteNumber = param1; 221 event2.amount = p.readUInt8(); 222 return event2; 223 case 11: 224 event2.type = "controller"; 225 event2.controllerType = param1; 226 event2.value = p.readUInt8(); 227 return event2; 228 case 12: 229 event2.type = "programChange"; 230 event2.programNumber = param1; 231 return event2; 232 case 13: 233 event2.type = "channelAftertouch"; 234 event2.amount = param1; 235 return event2; 236 case 14: 237 event2.type = "pitchBend"; 238 event2.value = param1 + (p.readUInt8() << 7) - 8192; 239 return event2; 240 default: 241 throw "Unrecognised MIDI event type: " + eventType; 242 } 243 } 244 } 245 } 246 function Parser(data) { 247 this.buffer = data; 248 this.bufferLen = this.buffer.length; 249 this.pos = 0; 250 } 251 Parser.prototype.eof = function() { 252 return this.pos >= this.bufferLen; 253 }; 254 Parser.prototype.readUInt8 = function() { 255 var result = this.buffer[this.pos]; 256 this.pos += 1; 257 return result; 258 }; 259 Parser.prototype.readInt8 = function() { 260 var u = this.readUInt8(); 261 if (u & 128) 262 return u - 256; 263 else 264 return u; 265 };
266 Parser.prototype.readUInt16 = function() { 267 var b0 = this.readUInt8(), b1 = this.readUInt8(); 268 return (b0 << 8) + b1; 269 }; 270 Parser.prototype.readInt16 = function() { 271 var u = this.readUInt16(); 272 if (u & 32768) 273 return u - 65536; 274 else 275 return u; 276 }; 277 Parser.prototype.readUInt24 = function() { 278 var b0 = this.readUInt8(), b1 = this.readUInt8(), b2 = this.readUInt8(); 279 return (b0 << 16) + (b1 << 8) + b2; 280 }; 281 Parser.prototype.readInt24 = function() { 282 var u = this.readUInt24(); 283 if (u & 8388608) 284 return u - 16777216; 285 else 286 return u; 287 }; 288 Parser.prototype.readUInt32 = function() { 289 var b0 = this.readUInt8(), b1 = this.readUInt8(), b2 = this.readUInt8(), b3 = this.readUInt8(); 290 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; 291 }; 292 Parser.prototype.readBytes = function(len) { 293 var bytes = this.buffer.slice(this.pos, this.pos + len); 294 this.pos += len; 295 return bytes; 296 }; 297 Parser.prototype.readString = function(len) { 298 var bytes = this.readBytes(len); 299 return String.fromCharCode.apply(null, bytes); 300 }; 301 Parser.prototype.readVarInt = function() { 302 var result = 0; 303 while (!this.eof()) { 304 var b = this.readUInt8(); 305 if (b & 128) { 306 result += b & 127; 307 result <<= 7; 308 } else { 309 return result + b; 310 } 311 } 312 return result; 313 }; 314 Parser.prototype.readChunk = function() { 315 var id = this.readString(4); 316 var length = this.readUInt32(); 317 var data = this.readBytes(length); 318 return { 319 id, 320 length, 321 data 322 }; 323 }; 324 var midiParser = parseMidi; 325 function writeMidi(data, opts) { 326 if (typeof data !== "object") 327 throw "Invalid MIDI data"; 328 opts = opts || {}; 329 var header = data.header || {}; 330 var tracks = data.tracks || []; 331 var i, len = tracks.length; 332 var w = new Writer(); 333 writeHeader(w, header, len); 334 for (i = 0; i < len; i++) { 335 writeTrack(w, tracks[i], opts); 336 } 337 return w.buffer; 338 } 339 function writeHeader(w, header, numTracks) { 340 var format = header.format == null ? 1 : header.format; 341 var timeDivision = 128; 342 if (header.timeDivision) { 343 timeDivision = header.timeDivision; 344 } else if (header.ticksPerFrame && header.framesPerSecond) { 345 timeDivision = -(header.framesPerSecond & 255) << 8 | header.ticksPerFrame & 255; 346 } else if (header.ticksPerBeat) { 347 timeDivision = header.ticksPerBeat & 32767; 348 } 349 var h = new Writer(); 350 h.writeUInt16(format); 351 h.writeUInt16(numTracks); 352 h.writeUInt16(timeDivision); 353 w.writeChunk("MThd", h.buffer); 354 } 355 function writeTrack(w, track, opts) { 356 var t = new Writer(); 357 var i, len = track.length; 358 var eventTypeByte = null; 359 for (i = 0; i < len; i++) { 360 if (opts.running === false || !opts.running && !track[i].running) eventTypeByte = null; 361 eventTypeByte = writeEvent(t, track[i], eventTypeByte, opts.useByte9ForNoteOff); 362 } 363 w.writeChunk("MTrk", t.buffer); 364 } 365 function writeEvent(w, event, lastEventTypeByte, useByte9ForNoteOff) { 366 var type = event.type; 367 var deltaTime = event.deltaTime; 368 var text = event.text || ""; 369 var data = event.data || []; 370 var eventTypeByte = null; 371 w.writeVarInt(deltaTime); 372 switch (type) { 373 case "sequenceNumber": 374 w.writeUInt8(255); 375 w.writeUInt8(0); 376 w.writeVarInt(2); 377 w.writeUInt16(event.number); 378 break; 379 case "text": 380 w.writeUInt8(255); 381 w.writeUInt8(1); 382 w.writeVarInt(text.length); 383 w.writeString(text); 384 break; 385 case "copyrightNotice": 386 w.writeUInt8(255); 387 w.writeUInt8(2); 388 w.writeVarInt(text.length); 389 w.writeString(text); 390 break; 391 case "trackName": 392 w.writeUInt8(255); 393 w.writeUInt8(3); 394 w.writeVarInt(text.length); 395 w.writeString(text); 396 break; 397 case "instrumentName": 398 w.writeUInt8(255); 399 w.writeUInt8(4); 400 w.writeVarInt(text.length); 401 w.writeString(text); 402 break; 403 case "lyrics": 404 w.writeUInt8(255); 405 w.writeUInt8(5); 406 w.writeVarInt(text.length); 407 w.writeString(text); 408 break; 409 case "marker": 410 w.writeUInt8(255); 411 w.writeUInt8(6); 412 w.writeVarInt(text.length); 413 w.writeString(text); 414 break; 415 case "cuePoint": 416 w.writeUInt8(255); 417 w.writeUInt8(7); 418 w.writeVarInt(text.length); 419 w.writeString(text); 420 break; 421 case "channelPrefix": 422 w.writeUInt8(255); 423 w.writeUInt8(32); 424 w.writeVarInt(1); 425 w.writeUInt8(event.channel); 426 break; 427 case "portPrefix": 428 w.writeUInt8(255); 429 w.writeUInt8(33); 430 w.writeVarInt(1); 431 w.writeUInt8(event.port); 432 break; 433 case "endOfTrack": 434 w.writeUInt8(255); 435 w.writeUInt8(47); 436 w.writeVarInt(0); 437 break; 438 case "setTempo": 439 w.writeUInt8(255); 440 w.writeUInt8(81); 441 w.writeVarInt(3); 442 w.writeUInt24(event.microsecondsPerBeat); 443 break; 444 case "smpteOffset": 445 w.writeUInt8(255); 446 w.writeUInt8(84); 447 w.writeVarInt(5); 448 var FRAME_RATES = { 24: 0, 25: 32, 29: 64, 30: 96 }; 449 var hourByte = event.hour & 31 | FRAME_RATES[event.frameRate]; 450 w.writeUInt8(hourByte); 451 w.writeUInt8(event.min); 452 w.writeUInt8(event.sec); 453 w.writeUInt8(event.frame); 454 w.writeUInt8(event.subFrame); 455 break; 456 case "timeSignature": 457 w.writeUInt8(255); 458 w.writeUInt8(88); 459 w.writeVarInt(4); 460 w.writeUInt8(event.numerator); 461 var denominator = Math.floor(Math.log(event.denominator) / Math.LN2) & 255; 462 w.writeUInt8(denominator); 463 w.writeUInt8(event.metronome); 464 w.writeUInt8(event.thirtyseconds || 8); 465 break; 466 case "keySignature": 467 w.writeUInt8(255); 468 w.writeUInt8(89); 469 w.writeVarInt(2); 470 w.writeInt8(event.key); 471 w.writeUInt8(event.scale); 472 break; 473 case "sequencerSpecific": 474 w.writeUInt8(255); 475 w.writeUInt8(127); 476 w.writeVarInt(data.length); 477 w.writeBytes(data); 478 break; 479 case "unknownMeta": 480 if (event.metatypeByte != null) { 481 w.writeUInt8(255); 482 w.writeUInt8(event.metatypeByte); 483 w.writeVarInt(data.length); 484 w.writeBytes(data); 485 } 486 break; 487 case "sysEx": 488 w.writeUInt8(240); 489 w.writeVarInt(data.length); 490 w.writeBytes(data); 491 break; 492 case "endSysEx": 493 w.writeUInt8(247); 494 w.writeVarInt(data.length); 495 w.writeBytes(data); 496 break; 497 case "noteOff": 498 var noteByte = useByte9ForNoteOff !== false && event.byte9 || useByte9ForNoteOff && event.velocity == 0 ? 144 : 128; 499 eventTypeByte = noteByte | event.channel; 500 if (eventTypeByte !== lastEventTypeByte) w.writeUInt8(eventTypeByte); 501 w.writeUInt8(event.noteNumber); 502 w.writeUInt8(event.velocity); 503 break; 504 case "noteOn": 505 eventTypeByte = 144 | event.channel; 506 if (eventTypeByte !== lastEventTypeByte) w.writeUInt8(eventTypeByte); 507 w.writeUInt8(event.noteNumber); 508 w.writeUInt8(event.velocity); 509 break; 510 case "noteAftertouch": 511 eventTypeByte = 160 | event.channel; 512 if (eventTypeByte !== lastEventTypeByte) w.writeUInt8(eventTypeByte); 513 w.writeUInt8(event.noteNumber); 514 w.writeUInt8(event.amount); 515 break; 516 case "controller": 517 eventTypeByte = 176 | event.channel; 518 if (eventTypeByte !== lastEventTypeByte) w.writeUInt8(eventTypeByte); 519 w.writeUInt8(event.controllerType); 520 w.writeUInt8(event.value); 521 break; 522 case "programChange": 523 eventTypeByte = 192 | event.channel; 524 if (eventTypeByte !== lastEventTypeByte) w.writeUInt8(eventTypeByte); 525 w.writeUInt8(event.programNumber); 526 break; 527 case "channelAftertouch": 528 eventTypeByte = 208 | event.channel; 529 if (eventTypeByte !== lastEventTypeByte) w.writeUInt8(eventTypeByte); 530 w.writeUInt8(event.amount); 531 break; 532 case "pitchBend": 533 eventTypeByte = 224 | event.channel; 534 if (eventTypeByte !== lastEventTypeByte) w.writeUInt8(eventTypeByte); 535 var value14 = 8192 + event.value; 536 var lsb14 = value14 & 127; 537 var msb14 = value14 >> 7 & 127; 538 w.writeUInt8(lsb14); 539 w.writeUInt8(msb14); 540 break; 541 default: 542 throw "Unrecognized event type: " + type; 543 } 544 return eventTypeByte; 545 } 546 function Writer() { 547 this.buffer = []; 548 } 549 Writer.prototype.writeUInt8 = function(v) { 550 this.buffer.push(v & 255); 551 }; 552 Writer.prototype.writeInt8 = Writer.prototype.writeUInt8; 553 Writer.prototype.writeUInt16 = function(v) { 554 var b0 = v >> 8 & 255, b1 = v & 255; 555 this.writeUInt8(b0); 556 this.writeUInt8(b1); 557 }; 558 Writer.prototype.writeInt16 = Writer.prototype.writeUInt16; 559 Writer.prototype.writeUInt24 = function(v) { 560 var b0 = v >> 16 & 255, b1 = v >> 8 & 255, b2 = v & 255; 561 this.writeUInt8(b0); 562 this.writeUInt8(b1); 563 this.writeUInt8(b2); 564 }; 565 Writer.prototype.writeInt24 = Writer.prototype.writeUInt24; 566 Writer.prototype.writeUInt32 = function(v) { 567 var b0 = v >> 24 & 255, b1 = v >> 16 & 255, b2 = v >> 8 & 255, b3 = v & 255; 568 this.writeUInt8(b0); 569 this.writeUInt8(b1); 570 this.writeUInt8(b2); 571 this.writeUInt8(b3); 572 }; 573 Writer.prototype.writeInt32 = Writer.prototype.writeUInt32; 574 Writer.prototype.writeBytes = function(arr) { 575 this.buffer = this.buffer.concat(Array.prototype.slice.call(arr, 0)); 576 }; 577 Writer.prototype.writeString = function(str) { 578 var i, len = str.length, arr = []; 579 for (i = 0; i < len; i++) { 580 arr.push(str.codePointAt(i)); 581 } 582 this.writeBytes(arr); 583 }; 584 Writer.prototype.writeVarInt = function(v) { 585 if (v < 0) throw "Cannot write negative variable-length integer"; 586 if (v <= 127) { 587 this.writeUInt8(v); 588 } else { 589 var i = v; 590 var bytes = []; 591 bytes.push(i & 127); 592 i >>= 7; 593 while (i) { 594 var b = i & 127 | 128; 595 bytes.push(b); 596 i >>= 7; 597 } 598 this.writeBytes(bytes.reverse()); 599 } 600 }; 601 Writer.prototype.writeChunk = function(id, data) { 602 this.writeString(id); 603 this.writeUInt32(data.length); 604 this.writeBytes(data); 605 }; 606 var midiWriter = writeMidi; 607 midiFile.parseMidi = midiParser; 608 midiFile.writeMidi = midiWriter; 609 var Header = {}; 610 var BinarySearch = {}; 611 Object.defineProperty(BinarySearch, "__esModule", { value: true }); 612 BinarySearch.insert = BinarySearch.search = void 0; 613 function search(array, value, prop) { 614 if (prop === void 0) { 615 prop = "ticks"; 616 } 617 var beginning = 0; 618 var len = array.length; 619 var end = len; 620 if (len > 0 && array[len - 1][prop] <= value) { 621 return len - 1; 622 } 623 while (beginning < end) { 624 var midPoint = Math.floor(beginning + (end - beginning) / 2); 625 var event_1 = array[midPoint]; 626 var nextEvent = array[midPoint + 1]; 627 if (event_1[prop] === value) { 628 for (var i = midPoint; i < array.length; i++) { 629 var testEvent = array[i]; 630 if (testEvent[prop] === value) { 631 midPoint = i; 632 } 633 } 634 return midPoint; 635 } else if (event_1[prop] < value && nextEvent[prop] > value) { 636 return midPoint; 637 } else if (event_1[prop] > value) { 638 end = midPoint; 639 } else if (event_1[prop] < value) { 640 beginning = midPoint + 1; 641 } 642 } 643 return -1; 644 } 645 BinarySearch.search = search; 646 function insert(array, event, prop) { 647 if (prop === void 0) { 648 prop = "ticks"; 649 } 650 if (array.length) { 651 var index = search(array, event[prop], prop); 652 array.splice(index + 1, 0, event); 653 } else { 654 array.push(event); 655 } 656 } 657 BinarySearch.insert = insert; 658 (function(exports$1) { 659 Object.defineProperty(exports$1, "__esModule", { value: true }); 660 exports$1.Header = exports$1.keySignatureKeys = void 0; 661 var BinarySearch_12 = BinarySearch; 662 var privatePPQMap = /* @__PURE__ */ new WeakMap(); 663 exports$1.keySignatureKeys = [ 664 "Cb", 665 "Gb", 666 "Db", 667 "Ab", 668 "Eb", 669 "Bb", 670 "F", 671 "C", 672 "G", 673 "D", 674 "A", 675 "E", 676 "B", 677 "F#", 678 "C#" 679 ]; 680 var Header2 = ( 681 /** @class */ 682 function() { 683 function Header3(midiData) { 684 var _this = this; 685 this.tempos = []; 686 this.timeSignatures = []; 687 this.keySignatures = []; 688 this.meta = []; 689 this.name = ""; 690 privatePPQMap.set(this, 480); 691 if (midiData) { 692 privatePPQMap.set(this, midiData.header.ticksPerBeat); 693 midiData.tracks.forEach(function(track) { 694 track.forEach(function(event) { 695 if (event.meta) { 696 if (event.type === "timeSignature") { 697 _this.timeSignatures.push({ 698 ticks: event.absoluteTime, 699 timeSignature: [ 700 event.numerator, 701 event.denominator 702 ] 703 }); 704 } else if (event.type === "setTempo") { 705 _this.tempos.push({ 706 bpm: 6e7 / event.microsecondsPerBeat, 707 ticks: event.absoluteTime 708 }); 709 } else if (event.type === "keySignature") { 710 _this.keySignatures.push({ 711 key: exports$1.keySignatureKeys[event.key + 7], 712 scale: event.scale === 0 ? "major" : "minor", 713 ticks: event.absoluteTime 714 }); 715 } 716 } 717 }); 718 }); 719 var firstTrackCurrentTicks_1 = 0;
720 midiData.tracks[0].forEach(function(event) { 721 firstTrackCurrentTicks_1 += event.deltaTime; 722 if (event.meta) { 723 if (event.type === "trackName") { 724 _this.name = event.text; 725 } else if (event.type === "text" || event.type === "cuePoint" || event.type === "marker" || event.type === "lyrics") { 726 _this.meta.push({ 727 text: event.text, 728 ticks: firstTrackCurrentTicks_1, 729 type: event.type 730 }); 731 } 732 } 733 }); 734 this.update(); 735 } 736 } 737 Header3.prototype.update = function() { 738 var _this = this; 739 var currentTime = 0; 740 var lastEventBeats = 0; 741 this.tempos.sort(function(a, b) { 742 return a.ticks - b.ticks; 743 }); 744 this.tempos.forEach(function(event, index) { 745 var lastBPM = index > 0 ? _this.tempos[index - 1].bpm : _this.tempos[0].bpm; 746 var beats = event.ticks / _this.ppq - lastEventBeats; 747 var elapsedSeconds = 60 / lastBPM * beats; 748 event.time = elapsedSeconds + currentTime; 749 currentTime = event.time; 750 lastEventBeats += beats; 751 }); 752 this.timeSignatures.sort(function(a, b) { 753 return a.ticks - b.ticks; 754 }); 755 this.timeSignatures.forEach(function(event, index) { 756 var lastEvent = index > 0 ? _this.timeSignatures[index - 1] : _this.timeSignatures[0]; 757 var elapsedBeats = (event.ticks - lastEvent.ticks) / _this.ppq; 758 var elapsedMeasures = elapsedBeats / lastEvent.timeSignature[0] / (lastEvent.timeSignature[1] / 4); 759 lastEvent.measures = lastEvent.measures || 0; 760 event.measures = elapsedMeasures + lastEvent.measures; 761 }); 762 }; 763 Header3.prototype.ticksToSeconds = function(ticks) { 764 var index = (0, BinarySearch_12.search)(this.tempos, ticks); 765 if (index !== -1) { 766 var tempo = this.tempos[index]; 767 var tempoTime = tempo.time; 768 var elapsedBeats = (ticks - tempo.ticks) / this.ppq; 769 return tempoTime + 60 / tempo.bpm * elapsedBeats; 770 } else { 771 var beats = ticks / this.ppq; 772 return 60 / 120 * beats; 773 } 774 }; 775 Header3.prototype.ticksToMeasures = function(ticks) { 776 var index = (0, BinarySearch_12.search)(this.timeSignatures, ticks); 777 if (index !== -1) { 778 var timeSigEvent = this.timeSignatures[index]; 779 var elapsedBeats = (ticks - timeSigEvent.ticks) / this.ppq; 780 return timeSigEvent.measures + elapsedBeats / (timeSigEvent.timeSignature[0] / timeSigEvent.timeSignature[1]) / 4; 781 } else { 782 return ticks / this.ppq / 4; 783 } 784 }; 785 Object.defineProperty(Header3.prototype, "ppq", { 786 /** 787 * The number of ticks per quarter note. 788 */ 789 get: function() { 790 return privatePPQMap.get(this); 791 }, 792 enumerable: false, 793 configurable: true 794 }); 795 Header3.prototype.secondsToTicks = function(seconds) { 796 var index = (0, BinarySearch_12.search)(this.tempos, seconds, "time"); 797 if (index !== -1) { 798 var tempo = this.tempos[index]; 799 var tempoTime = tempo.time; 800 var elapsedTime = seconds - tempoTime; 801 var elapsedBeats = elapsedTime / (60 / tempo.bpm); 802 return Math.round(tempo.ticks + elapsedBeats * this.ppq); 803 } else { 804 var beats = seconds / (60 / 120); 805 return Math.round(beats * this.ppq); 806 } 807 }; 808 Header3.prototype.toJSON = function() { 809 return { 810 keySignatures: this.keySignatures, 811 meta: this.meta, 812 name: this.name, 813 ppq: this.ppq, 814 tempos: this.tempos.map(function(t) { 815 return { 816 bpm: t.bpm, 817 ticks: t.ticks 818 }; 819 }), 820 timeSignatures: this.timeSignatures 821 }; 822 }; 823 Header3.prototype.fromJSON = function(json) { 824 this.name = json.name; 825 this.tempos = json.tempos.map(function(t) { 826 return Object.assign({}, t); 827 }); 828 this.timeSignatures = json.timeSignatures.map(function(t) { 829 return Object.assign({}, t); 830 }); 831 this.keySignatures = json.keySignatures.map(function(t) { 832 return Object.assign({}, t); 833 }); 834 this.meta = json.meta.map(function(t) { 835 return Object.assign({}, t); 836 }); 837 privatePPQMap.set(this, json.ppq); 838 this.update(); 839 }; 840 Header3.prototype.setTempo = function(bpm) { 841 this.tempos = [ 842 { 843 bpm, 844 ticks: 0 845 } 846 ]; 847 this.update(); 848 }; 849 return Header3; 850 }() 851 ); 852 exports$1.Header = Header2; 853 })(Header); 854 var Track$1 = {}; 855 var ControlChange = {}; 856 (function(exports$1) { 857 Object.defineProperty(exports$1, "__esModule", { value: true }); 858 exports$1.ControlChange = exports$1.controlChangeIds = exports$1.controlChangeNames = void 0; 859 exports$1.controlChangeNames = { 860 1: "modulationWheel", 861 2: "breath", 862 4: "footController", 863 5: "portamentoTime", 864 7: "volume", 865 8: "balance", 866 10: "pan", 867 64: "sustain", 868 65: "portamentoTime", 869 66: "sostenuto", 870 67: "softPedal", 871 68: "legatoFootswitch", 872 84: "portamentoControl" 873 }; 874 exports$1.controlChangeIds = Object.keys(exports$1.controlChangeNames).reduce(function(obj, key) { 875 obj[exports$1.controlChangeNames[key]] = key; 876 return obj; 877 }, {}); 878 var privateHeaderMap2 = /* @__PURE__ */ new WeakMap(); 879 var privateCCNumberMap = /* @__PURE__ */ new WeakMap(); 880 var ControlChange2 = ( 881 /** @class */ 882 function() { 883 function ControlChange3(event, header) { 884 privateHeaderMap2.set(this, header); 885 privateCCNumberMap.set(this, event.controllerType); 886 this.ticks = event.absoluteTime; 887 this.value = event.value; 888 } 889 Object.defineProperty(ControlChange3.prototype, "number", { 890 /** 891 * The controller number 892 */ 893 get: function() { 894 return privateCCNumberMap.get(this); 895 }, 896 enumerable: false, 897 configurable: true 898 });
899 Object.defineProperty(ControlChange3.prototype, "name", { 900 /** 901 * return the common name of the control number if it exists 902 */ 903 get: function() { 904 if (exports$1.controlChangeNames[this.number]) { 905 return exports$1.controlChangeNames[this.number]; 906 } else { 907 return null; 908 } 909 }, 910 enumerable: false, 911 configurable: true 912 }); 913 Object.defineProperty(ControlChange3.prototype, "time", { 914 /** 915 * The time of the event in seconds 916 */ 917 get: function() { 918 var header = privateHeaderMap2.get(this); 919 return header.ticksToSeconds(this.ticks); 920 }, 921 set: function(t) { 922 var header = privateHeaderMap2.get(this); 923 this.ticks = header.secondsToTicks(t); 924 }, 925 enumerable: false, 926 configurable: true 927 }); 928 ControlChange3.prototype.toJSON = function() { 929 return { 930 number: this.number, 931 ticks: this.ticks, 932 time: this.time, 933 value: this.value 934 }; 935 }; 936 return ControlChange3; 937 }() 938 ); 939 exports$1.ControlChange = ControlChange2; 940 })(ControlChange); 941 var ControlChanges = {}; 942 Object.defineProperty(ControlChanges, "__esModule", { value: true }); 943 ControlChanges.createControlChanges = void 0; 944 var ControlChange_1$1 = ControlChange; 945 function createControlChanges() { 946 return new Proxy({}, { 947 // tslint:disable-next-line: typedef 948 get: function(target, handler) { 949 if (target[handler]) { 950 return target[handler]; 951 } else if (ControlChange_1$1.controlChangeIds.hasOwnProperty(handler)) { 952 return target[ControlChange_1$1.controlChangeIds[handler]]; 953 } 954 }, 955 // tslint:disable-next-line: typedef 956 set: function(target, handler, value) { 957 if (ControlChange_1$1.controlChangeIds.hasOwnProperty(handler)) { 958 target[ControlChange_1$1.controlChangeIds[handler]] = value; 959 } else { 960 target[handler] = value; 961 } 962 return true; 963 } 964 }); 965 } 966 ControlChanges.createControlChanges = createControlChanges; 967 var PitchBend$1 = {}; 968 Object.defineProperty(PitchBend$1, "__esModule", { value: true }); 969 PitchBend$1.PitchBend = void 0; 970 var privateHeaderMap$2 = /* @__PURE__ */ new WeakMap(); 971 var PitchBend = ( 972 /** @class */ 973 function() { 974 function PitchBend2(event, header) { 975 privateHeaderMap$2.set(this, header); 976 this.ticks = event.absoluteTime; 977 this.value = event.value; 978 } 979 Object.defineProperty(PitchBend2.prototype, "time", { 980 /** 981 * The time of the event in seconds 982 */ 983 get: function() { 984 var header = privateHeaderMap$2.get(this); 985 return header.ticksToSeconds(this.ticks); 986 }, 987 set: function(t) { 988 var header = privateHeaderMap$2.get(this); 989 this.ticks = header.secondsToTicks(t); 990 }, 991 enumerable: false, 992 configurable: true 993 }); 994 PitchBend2.prototype.toJSON = function() { 995 return { 996 ticks: this.ticks, 997 time: this.time, 998 value: this.value 999 }; 1000 }; 1001 return PitchBend2; 1002 }() 1003 ); 1004 PitchBend$1.PitchBend = PitchBend; 1005 var Instrument$1 = {}; 1006 var InstrumentMaps = {}; 1007 Object.defineProperty(InstrumentMaps, "__esModule", { value: true }); 1008 InstrumentMaps.DrumKitByPatchID = InstrumentMaps.InstrumentFamilyByID = InstrumentMaps.instrumentByPatchID = void 0; 1009 InstrumentMaps.instrumentByPatchID = [ 1010 "acoustic grand piano", 1011 "bright acoustic piano", 1012 "electric grand piano", 1013 "honky-tonk piano", 1014 "electric piano 1", 1015 "electric piano 2", 1016 "harpsichord", 1017 "clavi", 1018 "celesta", 1019 "glockenspiel", 1020 "music box", 1021 "vibraphone", 1022 "marimba", 1023 "xylophone", 1024 "tubular bells", 1025 "dulcimer", 1026 "drawbar organ", 1027 "percussive organ", 1028 "rock organ", 1029 "church organ", 1030 "reed organ", 1031 "accordion", 1032 "harmonica", 1033 "tango accordion", 1034 "acoustic guitar (nylon)", 1035 "acoustic guitar (steel)", 1036 "electric guitar (jazz)", 1037 "electric guitar (clean)", 1038 "electric guitar (muted)", 1039 "overdriven guitar", 1040 "distortion guitar", 1041 "guitar harmonics", 1042 "acoustic bass", 1043 "electric bass (finger)", 1044 "electric bass (pick)", 1045 "fretless bass", 1046 "slap bass 1", 1047 "slap bass 2", 1048 "synth bass 1", 1049 "synth bass 2", 1050 "violin", 1051 "viola", 1052 "cello", 1053 "contrabass", 1054 "tremolo strings", 1055 "pizzicato strings", 1056 "orchestral harp", 1057 "timpani", 1058 "string ensemble 1", 1059 "string ensemble 2", 1060 "synthstrings 1", 1061 "synthstrings 2", 1062 "choir aahs", 1063 "voice oohs", 1064 "synth voice", 1065 "orchestra hit", 1066 "trumpet", 1067 "trombone", 1068 "tuba", 1069 "muted trumpet", 1070 "french horn", 1071 "brass section", 1072 "synthbrass 1", 1073 "synthbrass 2",
1074 "soprano sax", 1075 "alto sax", 1076 "tenor sax", 1077 "baritone sax", 1078 "oboe", 1079 "english horn", 1080 "bassoon", 1081 "clarinet", 1082 "piccolo", 1083 "flute", 1084 "recorder", 1085 "pan flute", 1086 "blown bottle", 1087 "shakuhachi", 1088 "whistle", 1089 "ocarina", 1090 "lead 1 (square)", 1091 "lead 2 (sawtooth)", 1092 "lead 3 (calliope)", 1093 "lead 4 (chiff)", 1094 "lead 5 (charang)", 1095 "lead 6 (voice)", 1096 "lead 7 (fifths)", 1097 "lead 8 (bass + lead)", 1098 "pad 1 (new age)", 1099 "pad 2 (warm)", 1100 "pad 3 (polysynth)", 1101 "pad 4 (choir)", 1102 "pad 5 (bowed)", 1103 "pad 6 (metallic)", 1104 "pad 7 (halo)", 1105 "pad 8 (sweep)", 1106 "fx 1 (rain)", 1107 "fx 2 (soundtrack)", 1108 "fx 3 (crystal)", 1109 "fx 4 (atmosphere)", 1110 "fx 5 (brightness)", 1111 "fx 6 (goblins)", 1112 "fx 7 (echoes)", 1113 "fx 8 (sci-fi)", 1114 "sitar", 1115 "banjo", 1116 "shamisen", 1117 "koto", 1118 "kalimba", 1119 "bag pipe", 1120 "fiddle", 1121 "shanai", 1122 "tinkle bell", 1123 "agogo", 1124 "steel drums", 1125 "woodblock", 1126 "taiko drum", 1127 "melodic tom", 1128 "synth drum", 1129 "reverse cymbal", 1130 "guitar fret noise", 1131 "breath noise", 1132 "seashore", 1133 "bird tweet", 1134 "telephone ring", 1135 "helicopter", 1136 "applause", 1137 "gunshot" 1138 ]; 1139 InstrumentMaps.InstrumentFamilyByID = [ 1140 "piano", 1141 "chromatic percussion", 1142 "organ", 1143 "guitar", 1144 "bass", 1145 "strings", 1146 "ensemble", 1147 "brass", 1148 "reed", 1149 "pipe", 1150 "synth lead", 1151 "synth pad", 1152 "synth effects", 1153 "world", 1154 "percussive", 1155 "sound effects" 1156 ]; 1157 InstrumentMaps.DrumKitByPatchID = { 1158 0: "standard kit", 1159 8: "room kit", 1160 16: "power kit", 1161 24: "electronic kit", 1162 25: "tr-808 kit", 1163 32: "jazz kit", 1164 40: "brush kit", 1165 48: "orchestra kit", 1166 56: "sound fx kit" 1167 }; 1168 Object.defineProperty(Instrument$1, "__esModule", { value: true }); 1169 Instrument$1.Instrument = void 0; 1170 var InstrumentMaps_1 = InstrumentMaps; 1171 var privateTrackMap = /* @__PURE__ */ new WeakMap(); 1172 var Instrument = ( 1173 /** @class */ 1174 function() { 1175 function Instrument2(trackData, track) { 1176 this.number = 0; 1177 privateTrackMap.set(this, track); 1178 this.number = 0; 1179 if (trackData) { 1180 var programChange = trackData.find(function(e) { 1181 return e.type === "programChange"; 1182 }); 1183 if (programChange) { 1184 this.number = programChange.programNumber; 1185 } 1186 } 1187 } 1188 Object.defineProperty(Instrument2.prototype, "name", { 1189 /** 1190 * The common name of the instrument. 1191 */ 1192 get: function() { 1193 if (this.percussion) { 1194 return InstrumentMaps_1.DrumKitByPatchID[this.number]; 1195 } else { 1196 return InstrumentMaps_1.instrumentByPatchID[this.number]; 1197 } 1198 }, 1199 set: function(n) { 1200 var patchNumber = InstrumentMaps_1.instrumentByPatchID.indexOf(n); 1201 if (patchNumber !== -1) { 1202 this.number = patchNumber; 1203 } 1204 }, 1205 enumerable: false, 1206 configurable: true 1207 }); 1208 Object.defineProperty(Instrument2.prototype, "family", { 1209 /** 1210 * The instrument family, e.g. "piano". 1211 */ 1212 get: function() { 1213 if (this.percussion) { 1214 return "drums"; 1215 } else { 1216 return InstrumentMaps_1.InstrumentFamilyByID[Math.floor(this.number / 8)]; 1217 } 1218 }, 1219 enumerable: false, 1220 configurable: true 1221 }); 1222 Object.defineProperty(Instrument2.prototype, "percussion", { 1223 /** 1224 * If the instrument is a percussion instrument. 1225 */ 1226 get: function() { 1227 var track = privateTrackMap.get(this); 1228 return track.channel === 9; 1229 }, 1230 enumerable: false, 1231 configurable: true 1232 }); 1233 Instrument2.prototype.toJSON = function() { 1234 return { 1235 family: this.family, 1236 number: this.number, 1237 name: this.name 1238 }; 1239 }; 1240 Instrument2.prototype.fromJSON = function(json) { 1241 this.number = json.number; 1242 }; 1243 return Instrument2; 1244 }() 1245 ); 1246 Instrument$1.Instrument = Instrument; 1247 var Note$1 = {}; 1248 Object.defineProperty(Note$1, "__esModule", { value: true }); 1249 Note$1.Note = void 0; 1250 function midiToPitch(midi) { 1251 var octave = Math.floor(midi / 12) - 1; 1252 return midiToPitchClass(midi) + octave.toString(); 1253 } 1254 function midiToPitchClass(midi) { 1255 var scaleIndexToNote = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; 1256 var note = midi % 12; 1257 return scaleIndexToNote[note]; 1258 } 1259 function pitchClassToMidi(pitch) { 1260 var scaleIndexToNote = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; 1261 return scaleIndexToNote.indexOf(pitch); 1262 } 1263 var pitchToMidi = /* @__PURE__ */ function() { 1264 var regexp = /^([a-g]{1}(?:b|#|x|bb)?)(-?[0-9]+)/i; 1265 var noteToScaleIndex = { 1266 // tslint:disable-next-line: object-literal-sort-keys 1267 cbb: -2, 1268 cb: -1, 1269 c: 0, 1270 "c#": 1, 1271 cx: 2, 1272 dbb: 0, 1273 db: 1, 1274 d: 2, 1275 "d#": 3, 1276 dx: 4, 1277 ebb: 2, 1278 eb: 3, 1279 e: 4, 1280 "e#": 5, 1281 ex: 6, 1282 fbb: 3, 1283 fb: 4, 1284 f: 5, 1285 "f#": 6, 1286 fx: 7, 1287 gbb: 5, 1288 gb: 6, 1289 g: 7, 1290 "g#": 8, 1291 gx: 9, 1292 abb: 7, 1293 ab: 8, 1294 a: 9, 1295 "a#": 10, 1296 ax: 11, 1297 bbb: 9, 1298 bb: 10, 1299 b: 11, 1300 "b#": 12, 1301 bx: 13 1302 }; 1303 return function(note) { 1304 var split = regexp.exec(note); 1305 var pitch = split[1]; 1306 var octave = split[2]; 1307 var index = noteToScaleIndex[pitch.toLowerCase()]; 1308 return index + (parseInt(octave, 10) + 1) * 12; 1309 }; 1310 }(); 1311 var privateHeaderMap$1 = /* @__PURE__ */ new WeakMap(); 1312 var Note = ( 1313 /** @class */ 1314 function() { 1315 function Note2(noteOn, noteOff, header) { 1316 privateHeaderMap$1.set(this, header); 1317 this.midi = noteOn.midi; 1318 this.velocity = noteOn.velocity; 1319 this.noteOffVelocity = noteOff.velocity; 1320 this.ticks = noteOn.ticks; 1321 this.durationTicks = noteOff.ticks - noteOn.ticks; 1322 }
1323 Object.defineProperty(Note2.prototype, "name", { 1324 /** 1325 * The note name and octave in scientific pitch notation, e.g. "C4". 1326 */ 1327 get: function() { 1328 return midiToPitch(this.midi); 1329 }, 1330 set: function(n) { 1331 this.midi = pitchToMidi(n); 1332 }, 1333 enumerable: false, 1334 configurable: true 1335 }); 1336 Object.defineProperty(Note2.prototype, "octave", { 1337 /** 1338 * The notes octave number. 1339 */ 1340 get: function() { 1341 return Math.floor(this.midi / 12) - 1; 1342 }, 1343 set: function(o) { 1344 var diff = o - this.octave; 1345 this.midi += diff * 12; 1346 }, 1347 enumerable: false, 1348 configurable: true 1349 }); 1350 Object.defineProperty(Note2.prototype, "pitch", { 1351 /** 1352 * The pitch class name. e.g. "A". 1353 */ 1354 get: function() { 1355 return midiToPitchClass(this.midi); 1356 }, 1357 set: function(p) { 1358 this.midi = 12 * (this.octave + 1) + pitchClassToMidi(p); 1359 }, 1360 enumerable: false, 1361 configurable: true 1362 }); 1363 Object.defineProperty(Note2.prototype, "duration", { 1364 /** 1365 * The duration of the segment in seconds. 1366 */ 1367 get: function() { 1368 var header = privateHeaderMap$1.get(this); 1369 return header.ticksToSeconds(this.ticks + this.durationTicks) - header.ticksToSeconds(this.ticks); 1370 }, 1371 set: function(d) { 1372 var header = privateHeaderMap$1.get(this); 1373 var noteEndTicks = header.secondsToTicks(this.time + d); 1374 this.durationTicks = noteEndTicks - this.ticks; 1375 }, 1376 enumerable: false, 1377 configurable: true 1378 }); 1379 Object.defineProperty(Note2.prototype, "time", { 1380 /** 1381 * The time of the event in seconds. 1382 */ 1383 get: function() { 1384 var header = privateHeaderMap$1.get(this); 1385 return header.ticksToSeconds(this.ticks); 1386 }, 1387 set: function(t) { 1388 var header = privateHeaderMap$1.get(this); 1389 this.ticks = header.secondsToTicks(t); 1390 }, 1391 enumerable: false, 1392 configurable: true 1393 }); 1394 Object.defineProperty(Note2.prototype, "bars", { 1395 /** 1396 * The number of measures (and partial measures) to this beat. 1397 * Takes into account time signature changes. 1398 * @readonly 1399 */ 1400 get: function() { 1401 var header = privateHeaderMap$1.get(this); 1402 return header.ticksToMeasures(this.ticks); 1403 }, 1404 enumerable: false, 1405 configurable: true 1406 }); 1407 Note2.prototype.toJSON = function() { 1408 return { 1409 duration: this.duration, 1410 durationTicks: this.durationTicks, 1411 midi: this.midi, 1412 name: this.name, 1413 ticks: this.ticks, 1414 time: this.time, 1415 velocity: this.velocity 1416 }; 1417 }; 1418 return Note2; 1419 }() 1420 ); 1421 Note$1.Note = Note; 1422 Object.defineProperty(Track$1, "__esModule", { value: true }); 1423 Track$1.Track = void 0; 1424 var BinarySearch_1 = BinarySearch; 1425 var ControlChange_1 = ControlChange; 1426 var ControlChanges_1 = ControlChanges; 1427 var PitchBend_1 = PitchBend$1; 1428 var Instrument_1 = Instrument$1; 1429 var Note_1 = Note$1; 1430 var privateHeaderMap = /* @__PURE__ */ new WeakMap(); 1431 var Track = ( 1432 /** @class */ 1433 function() { 1434 function Track2(trackData, header) { 1435 var _this = this; 1436 this.name = ""; 1437 this.notes = []; 1438 this.controlChanges = (0, ControlChanges_1.createControlChanges)(); 1439 this.pitchBends = []; 1440 privateHeaderMap.set(this, header); 1441 if (trackData) { 1442 var nameEvent = trackData.find(function(e) { 1443 return e.type === "trackName"; 1444 }); 1445 this.name = nameEvent ? nameEvent.text : ""; 1446 } 1447 this.instrument = new Instrument_1.Instrument(trackData, this); 1448 this.channel = 0; 1449 if (trackData) { 1450 var noteOns = trackData.filter(function(event) { 1451 return event.type === "noteOn"; 1452 }); 1453 var noteOffs = trackData.filter(function(event) { 1454 return event.type === "noteOff"; 1455 }); 1456 var _loop_1 = function() { 1457 var currentNote = noteOns.shift(); 1458 this_1.channel = currentNote.channel; 1459 var offIndex = noteOffs.findIndex(function(note) { 1460 return note.noteNumber === currentNote.noteNumber && note.absoluteTime >= currentNote.absoluteTime; 1461 }); 1462 if (offIndex !== -1) { 1463 var noteOff = noteOffs.splice(offIndex, 1)[0]; 1464 this_1.addNote({ 1465 durationTicks: noteOff.absoluteTime - currentNote.absoluteTime, 1466 midi: currentNote.noteNumber, 1467 noteOffVelocity: noteOff.velocity / 127, 1468 ticks: currentNote.absoluteTime, 1469 velocity: currentNote.velocity / 127 1470 }); 1471 } 1472 }; 1473 var this_1 = this; 1474 while (noteOns.length) { 1475 _loop_1(); 1476 } 1477 var controlChanges = trackData.filter(function(event) { 1478 return event.type === "controller"; 1479 });
1480 controlChanges.forEach(function(event) { 1481 _this.addCC({ 1482 number: event.controllerType, 1483 ticks: event.absoluteTime, 1484 value: event.value / 127 1485 }); 1486 }); 1487 var pitchBends = trackData.filter(function(event) { 1488 return event.type === "pitchBend"; 1489 }); 1490 pitchBends.forEach(function(event) { 1491 _this.addPitchBend({ 1492 ticks: event.absoluteTime, 1493 // Scale the value between -2^13 to 2^13 to -2 to 2. 1494 value: event.value / Math.pow(2, 13) 1495 }); 1496 }); 1497 var endOfTrackEvent = trackData.find(function(event) { 1498 return event.type === "endOfTrack"; 1499 }); 1500 this.endOfTrackTicks = endOfTrackEvent !== void 0 ? endOfTrackEvent.absoluteTime : void 0; 1501 } 1502 } 1503 Track2.prototype.addNote = function(props) { 1504 var header = privateHeaderMap.get(this); 1505 var note = new Note_1.Note({ 1506 midi: 0, 1507 ticks: 0, 1508 velocity: 1 1509 }, { 1510 ticks: 0, 1511 velocity: 0 1512 }, header); 1513 Object.assign(note, props); 1514 (0, BinarySearch_1.insert)(this.notes, note, "ticks"); 1515 return this; 1516 }; 1517 Track2.prototype.addCC = function(props) { 1518 var header = privateHeaderMap.get(this); 1519 var cc = new ControlChange_1.ControlChange({ 1520 controllerType: props.number 1521 }, header); 1522 delete props.number; 1523 Object.assign(cc, props); 1524 if (!Array.isArray(this.controlChanges[cc.number])) { 1525 this.controlChanges[cc.number] = []; 1526 } 1527 (0, BinarySearch_1.insert)(this.controlChanges[cc.number], cc, "ticks"); 1528 return this; 1529 }; 1530 Track2.prototype.addPitchBend = function(props) { 1531 var header = privateHeaderMap.get(this); 1532 var pb = new PitchBend_1.PitchBend({}, header); 1533 Object.assign(pb, props); 1534 (0, BinarySearch_1.insert)(this.pitchBends, pb, "ticks"); 1535 return this; 1536 }; 1537 Object.defineProperty(Track2.prototype, "duration", { 1538 /** 1539 * The end time of the last event in the track. 1540 */ 1541 get: function() { 1542 if (!this.notes.length) { 1543 return 0; 1544 } 1545 var maxDuration = this.notes[this.notes.length - 1].time + this.notes[this.notes.length - 1].duration; 1546 for (var i = 0; i < this.notes.length - 1; i++) { 1547 var duration = this.notes[i].time + this.notes[i].duration; 1548 if (maxDuration < duration) { 1549 maxDuration = duration; 1550 } 1551 } 1552 return maxDuration; 1553 }, 1554 enumerable: false, 1555 configurable: true 1556 }); 1557 Object.defineProperty(Track2.prototype, "durationTicks", { 1558 /** 1559 * The end time of the last event in the track in ticks. 1560 */ 1561 get: function() { 1562 if (!this.notes.length) { 1563 return 0; 1564 } 1565 var maxDuration = this.notes[this.notes.length - 1].ticks + this.notes[this.notes.length - 1].durationTicks; 1566 for (var i = 0; i < this.notes.length - 1; i++) { 1567 var duration = this.notes[i].ticks + this.notes[i].durationTicks; 1568 if (maxDuration < duration) { 1569 maxDuration = duration; 1570 } 1571 } 1572 return maxDuration; 1573 }, 1574 enumerable: false, 1575 configurable: true 1576 }); 1577 Track2.prototype.fromJSON = function(json) { 1578 var _this = this; 1579 this.name = json.name; 1580 this.channel = json.channel; 1581 this.instrument = new Instrument_1.Instrument(void 0, this); 1582 this.instrument.fromJSON(json.instrument); 1583 if (json.endOfTrackTicks !== void 0) { 1584 this.endOfTrackTicks = json.endOfTrackTicks; 1585 } 1586 for (var number in json.controlChanges) { 1587 if (json.controlChanges[number]) { 1588 json.controlChanges[number].forEach(function(cc) { 1589 _this.addCC({ 1590 number: cc.number, 1591 ticks: cc.ticks, 1592 value: cc.value 1593 }); 1594 }); 1595 } 1596 }
1597 json.notes.forEach(function(n) { 1598 _this.addNote({ 1599 durationTicks: n.durationTicks, 1600 midi: n.midi, 1601 ticks: n.ticks, 1602 velocity: n.velocity 1603 }); 1604 }); 1605 }; 1606 Track2.prototype.toJSON = function() { 1607 var controlChanges = {}; 1608 for (var i = 0; i < 127; i++) { 1609 if (this.controlChanges.hasOwnProperty(i)) { 1610 controlChanges[i] = this.controlChanges[i].map(function(c) { 1611 return c.toJSON(); 1612 }); 1613 } 1614 } 1615 var json = { 1616 channel: this.channel, 1617 controlChanges, 1618 pitchBends: this.pitchBends.map(function(pb) { 1619 return pb.toJSON(); 1620 }), 1621 instrument: this.instrument.toJSON(), 1622 name: this.name, 1623 notes: this.notes.map(function(n) { 1624 return n.toJSON(); 1625 }) 1626 }; 1627 if (this.endOfTrackTicks !== void 0) { 1628 json.endOfTrackTicks = this.endOfTrackTicks; 1629 } 1630 return json; 1631 }; 1632 return Track2; 1633 }() 1634 ); 1635 Track$1.Track = Track; 1636 var Encode = {}; 1637 function flatten(array) { 1638 var result = []; 1639 $flatten(array, result); 1640 return result; 1641 } 1642 function $flatten(array, result) { 1643 for (var i = 0; i < array.length; i++) { 1644 var value = array[i]; 1645 if (Array.isArray(value)) { 1646 $flatten(value, result); 1647 } else { 1648 result.push(value); 1649 } 1650 } 1651 } 1652 var dist_es2015 = /* @__PURE__ */ Object.freeze({ 1653 __proto__: null, 1654 flatten 1655 }); 1656 var require$$2 = /* @__PURE__ */ getAugmentedNamespace(dist_es2015); 1657 var __spreadArray = commonjsGlobal && commonjsGlobal.__spreadArray || function(to, from, pack) { 1658 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { 1659 if (ar || !(i in from)) { 1660 if (!ar) ar = Array.prototype.slice.call(from, 0, i); 1661 ar[i] = from[i]; 1662 } 1663 } 1664 return to.concat(ar || Array.prototype.slice.call(from)); 1665 }; 1666 Object.defineProperty(Encode, "__esModule", { value: true }); 1667 Encode.encode = void 0; 1668 var midi_file_1 = midiFile; 1669 var Header_1 = Header; 1670 var array_flatten_1 = require$$2; 1671 function encodeNote(note, channel) { 1672 return [ 1673 { 1674 absoluteTime: note.ticks, 1675 channel, 1676 deltaTime: 0, 1677 noteNumber: note.midi, 1678 type: "noteOn", 1679 velocity: Math.floor(note.velocity * 127) 1680 }, 1681 { 1682 absoluteTime: note.ticks + note.durationTicks, 1683 channel, 1684 deltaTime: 0, 1685 noteNumber: note.midi, 1686 type: "noteOff", 1687 velocity: Math.floor(note.noteOffVelocity * 127) 1688 } 1689 ]; 1690 } 1691 function encodeNotes(track) { 1692 return (0, array_flatten_1.flatten)(track.notes.map(function(note) { 1693 return encodeNote(note, track.channel); 1694 })); 1695 } 1696 function encodeControlChange(cc, channel) { 1697 return { 1698 absoluteTime: cc.ticks, 1699 channel, 1700 controllerType: cc.number, 1701 deltaTime: 0, 1702 type: "controller", 1703 value: Math.floor(cc.value * 127) 1704 }; 1705 } 1706 function encodeControlChanges(track) { 1707 var controlChanges = []; 1708 for (var i = 0; i < 127; i++) { 1709 if (track.controlChanges.hasOwnProperty(i)) { 1710 track.controlChanges[i].forEach(function(cc) { 1711 controlChanges.push(encodeControlChange(cc, track.channel)); 1712 }); 1713 } 1714 } 1715 return controlChanges; 1716 } 1717 function encodePitchBend(pb, channel) { 1718 return { 1719 absoluteTime: pb.ticks, 1720 channel, 1721 deltaTime: 0, 1722 type: "pitchBend", 1723 value: pb.value 1724 }; 1725 } 1726 function encodePitchBends(track) { 1727 var pitchBends = []; 1728 track.pitchBends.forEach(function(pb) { 1729 pitchBends.push(encodePitchBend(pb, track.channel)); 1730 }); 1731 return pitchBends; 1732 } 1733 function encodeInstrument(track) { 1734 return { 1735 absoluteTime: 0, 1736 channel: track.channel, 1737 deltaTime: 0, 1738 programNumber: track.instrument.number, 1739 type: "programChange" 1740 }; 1741 } 1742 function encodeTrackName(name) { 1743 return { 1744 absoluteTime: 0, 1745 deltaTime: 0, 1746 meta: true, 1747 text: name, 1748 type: "trackName" 1749 }; 1750 } 1751 function encodeTempo(tempo) { 1752 return { 1753 absoluteTime: tempo.ticks,
1754 deltaTime: 0, 1755 meta: true, 1756 microsecondsPerBeat: Math.floor(6e7 / tempo.bpm), 1757 type: "setTempo" 1758 }; 1759 } 1760 function encodeTimeSignature(timeSig) { 1761 return { 1762 absoluteTime: timeSig.ticks, 1763 deltaTime: 0, 1764 denominator: timeSig.timeSignature[1], 1765 meta: true, 1766 metronome: 24, 1767 numerator: timeSig.timeSignature[0], 1768 thirtyseconds: 8, 1769 type: "timeSignature" 1770 }; 1771 } 1772 function encodeKeySignature(keySig) { 1773 var keyIndex = Header_1.keySignatureKeys.indexOf(keySig.key); 1774 return { 1775 absoluteTime: keySig.ticks, 1776 deltaTime: 0, 1777 key: keyIndex + 7, 1778 meta: true, 1779 scale: keySig.scale === "major" ? 0 : 1, 1780 type: "keySignature" 1781 }; 1782 } 1783 function encodeText(textEvent) { 1784 return { 1785 absoluteTime: textEvent.ticks, 1786 deltaTime: 0, 1787 meta: true, 1788 text: textEvent.text, 1789 type: textEvent.type 1790 }; 1791 } 1792 function encode(midi) { 1793 var midiData = { 1794 header: { 1795 format: 1, 1796 numTracks: midi.tracks.length + 1, 1797 ticksPerBeat: midi.header.ppq 1798 }, 1799 tracks: __spreadArray([ 1800 __spreadArray(__spreadArray(__spreadArray(__spreadArray([ 1801 // The name data. 1802 { 1803 absoluteTime: 0, 1804 deltaTime: 0, 1805 meta: true, 1806 text: midi.header.name, 1807 type: "trackName" 1808 } 1809 ], midi.header.keySignatures.map(function(keySig) { 1810 return encodeKeySignature(keySig); 1811 }), true), midi.header.meta.map(function(e) { 1812 return encodeText(e); 1813 }), true), midi.header.tempos.map(function(tempo) { 1814 return encodeTempo(tempo); 1815 }), true), midi.header.timeSignatures.map(function(timeSig) { 1816 return encodeTimeSignature(timeSig); 1817 }), true) 1818 ], midi.tracks.map(function(track) { 1819 return __spreadArray(__spreadArray(__spreadArray([ 1820 // Add the name 1821 encodeTrackName(track.name), 1822 // the instrument 1823 encodeInstrument(track) 1824 ], encodeNotes(track), true), encodeControlChanges(track), true), encodePitchBends(track), true); 1825 }), true) 1826 }; 1827 midiData.tracks = midiData.tracks.map(function(track) { 1828 track = track.sort(function(a, b) { 1829 return a.absoluteTime - b.absoluteTime; 1830 }); 1831 var lastTime = 0; 1832 track.forEach(function(note) { 1833 note.deltaTime = note.absoluteTime - lastTime; 1834 lastTime = note.absoluteTime; 1835 delete note.absoluteTime; 1836 }); 1837 track.push({ 1838 deltaTime: 0, 1839 meta: true, 1840 type: "endOfTrack" 1841 }); 1842 return track; 1843 }); 1844 return new Uint8Array((0, midi_file_1.writeMidi)(midiData)); 1845 } 1846 Encode.encode = encode; 1847 (function(exports$1) { 1848 var __awaiter = commonjsGlobal && commonjsGlobal.__awaiter || function(thisArg, _arguments, P, generator) { 1849 function adopt(value) { 1850 return value instanceof P ? value : new P(function(resolve) { 1851 resolve(value); 1852 }); 1853 } 1854 return new (P || (P = Promise))(function(resolve, reject) { 1855 function fulfilled(value) { 1856 try { 1857 step(generator.next(value)); 1858 } catch (e) { 1859 reject(e); 1860 } 1861 } 1862 function rejected(value) { 1863 try { 1864 step(generator["throw"](value)); 1865 } catch (e) { 1866 reject(e); 1867 } 1868 } 1869 function step(result) { 1870 result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); 1871 } 1872 step((generator = generator.apply(thisArg, _arguments || [])).next()); 1873 }); 1874 }; 1875 var __generator = commonjsGlobal && commonjsGlobal.__generator || function(thisArg, body) { 1876 var _ = { label: 0, sent: function() { 1877 if (t[0] & 1) throw t[1]; 1878 return t[1]; 1879 }, trys: [], ops: [] }, f, y, t, g; 1880 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { 1881 return this; 1882 }), g; 1883 function verb(n) { 1884 return function(v) { 1885 return step([n, v]); 1886 }; 1887 } 1888 function step(op) { 1889 if (f) throw new TypeError("Generator is already executing."); 1890 while (_) try {
vendor: 6,106 bytes, lines 1891-2073
1891 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; 1892 if (y = 0, t) op = [op[0] & 2, t.value]; 1893 switch (op[0]) { 1894 case 0: 1895 case 1: 1896 t = op; 1897 break; 1898 case 4: 1899 _.label++; 1900 return { value: op[1], done: false }; 1901 case 5: 1902 _.label++; 1903 y = op[1]; 1904 op = [0]; 1905 continue; 1906 case 7: 1907 op = _.ops.pop(); 1908 _.trys.pop(); 1909 continue; 1910 default: 1911 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { 1912 _ = 0; 1913 continue; 1914 } 1915 if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { 1916 _.label = op[1]; 1917 break; 1918 } 1919 if (op[0] === 6 && _.label < t[1]) { 1920 _.label = t[1]; 1921 t = op; 1922 break; 1923 } 1924 if (t && _.label < t[2]) { 1925 _.label = t[2]; 1926 _.ops.push(op); 1927 break; 1928 } 1929 if (t[2]) _.ops.pop(); 1930 _.trys.pop(); 1931 continue; 1932 } 1933 op = body.call(thisArg, _); 1934 } catch (e) { 1935 op = [6, e]; 1936 y = 0; 1937 } finally { 1938 f = t = 0; 1939 } 1940 if (op[0] & 5) throw op[1]; 1941 return { value: op[0] ? op[1] : void 0, done: true }; 1942 } 1943 }; 1944 Object.defineProperty(exports$1, "__esModule", { value: true }); 1945 exports$1.Header = exports$1.Track = exports$1.Midi = void 0; 1946 var midi_file_12 = midiFile; 1947 var Header_12 = Header; 1948 var Track_1 = Track$1; 1949 var Encode_1 = Encode; 1950 var Midi2 = ( 1951 /** @class */ 1952 function() { 1953 function Midi3(midiArray) { 1954 var _this = this; 1955 var midiData = null; 1956 if (midiArray) { 1957 var midiArrayLike = midiArray instanceof ArrayBuffer ? new Uint8Array(midiArray) : midiArray; 1958 midiData = (0, midi_file_12.parseMidi)(midiArrayLike); 1959 midiData.tracks.forEach(function(track) { 1960 var currentTicks = 0; 1961 track.forEach(function(event) { 1962 currentTicks += event.deltaTime; 1963 event.absoluteTime = currentTicks; 1964 }); 1965 }); 1966 midiData.tracks = splitTracks(midiData.tracks); 1967 } 1968 this.header = new Header_12.Header(midiData); 1969 this.tracks = []; 1970 if (midiArray) { 1971 this.tracks = midiData.tracks.map(function(trackData) { 1972 return new Track_1.Track(trackData, _this.header); 1973 }); 1974 if (midiData.header.format === 1 && this.tracks[0].duration === 0) { 1975 this.tracks.shift(); 1976 } 1977 } 1978 } 1979 Midi3.fromUrl = function(url) { 1980 return __awaiter(this, void 0, void 0, function() { 1981 var response, arrayBuffer; 1982 return __generator(this, function(_a) { 1983 switch (_a.label) { 1984 case 0: 1985 return [4, fetch(url)]; 1986 case 1: 1987 response = _a.sent(); 1988 if (!response.ok) return [3, 3]; 1989 return [4, response.arrayBuffer()]; 1990 case 2: 1991 arrayBuffer = _a.sent(); 1992 return [2, new Midi3(arrayBuffer)]; 1993 case 3: 1994 throw new Error("Could not load '".concat(url, "'")); 1995 } 1996 }); 1997 }); 1998 }; 1999 Object.defineProperty(Midi3.prototype, "name", { 2000 /** 2001 * The name of the midi file, taken from the first track. 2002 */ 2003 get: function() { 2004 return this.header.name; 2005 }, 2006 set: function(n) { 2007 this.header.name = n; 2008 }, 2009 enumerable: false, 2010 configurable: true 2011 }); 2012 Object.defineProperty(Midi3.prototype, "duration", { 2013 /** 2014 * The total length of the file in seconds. 2015 */ 2016 get: function() { 2017 var durations = this.tracks.map(function(t) { 2018 return t.duration; 2019 }); 2020 return Math.max.apply(Math, durations); 2021 }, 2022 enumerable: false, 2023 configurable: true 2024 }); 2025 Object.defineProperty(Midi3.prototype, "durationTicks", { 2026 /** 2027 * The total length of the file in ticks. 2028 */ 2029 get: function() { 2030 var durationTicks = this.tracks.map(function(t) { 2031 return t.durationTicks; 2032 }); 2033 return Math.max.apply(Math, durationTicks); 2034 }, 2035 enumerable: false, 2036 configurable: true 2037 }); 2038 Midi3.prototype.addTrack = function() { 2039 var track = new Track_1.Track(void 0, this.header); 2040 this.tracks.push(track); 2041 return track; 2042 }; 2043 Midi3.prototype.toArray = function() { 2044 return (0, Encode_1.encode)(this); 2045 }; 2046 Midi3.prototype.toJSON = function() { 2047 return { 2048 header: this.header.toJSON(), 2049 tracks: this.tracks.map(function(track) { 2050 return track.toJSON(); 2051 }) 2052 }; 2053 }; 2054 Midi3.prototype.fromJSON = function(json) { 2055 var _this = this; 2056 this.header = new Header_12.Header(); 2057 this.header.fromJSON(json.header); 2058 this.tracks = json.tracks.map(function(trackJSON) { 2059 var track = new Track_1.Track(void 0, _this.header); 2060 track.fromJSON(trackJSON); 2061 return track; 2062 }); 2063 }; 2064 Midi3.prototype.clone = function() { 2065 var midi = new Midi3(); 2066 midi.fromJSON(this.toJSON()); 2067 return midi; 2068 }; 2069 return Midi3; 2070 }() 2071 ); 2072 exports$1.Midi = Midi2; 2073 var Track_2 = Track$1;
2074 Object.defineProperty(exports$1, "Track", { enumerable: true, get: function() { 2075 return Track_2.Track; 2076 } }); 2077 var Header_2 = Header; 2078 Object.defineProperty(exports$1, "Header", { enumerable: true, get: function() { 2079 return Header_2.Header; 2080 } }); 2081 function splitTracks(tracks) { 2082 var newTracks = []; 2083 for (var i = 0; i < tracks.length; i++) { 2084 var defaultTrack = newTracks.length; 2085 var trackMap = /* @__PURE__ */ new Map(); 2086 var currentProgram = Array(16).fill(0); 2087 for (var _i = 0, _a = tracks[i]; _i < _a.length; _i++) { 2088 var event_1 = _a[_i]; 2089 var targetTrack = defaultTrack; 2090 var channel = event_1.channel; 2091 if (channel !== void 0) { 2092 if (event_1.type === "programChange") { 2093 currentProgram[channel] = event_1.programNumber; 2094 } 2095 var program = currentProgram[channel]; 2096 var trackKey = "".concat(program, " ").concat(channel); 2097 if (trackMap.has(trackKey)) { 2098 targetTrack = trackMap.get(trackKey); 2099 } else { 2100 targetTrack = defaultTrack + trackMap.size; 2101 trackMap.set(trackKey, targetTrack); 2102 } 2103 } 2104 if (!newTracks[targetTrack]) { 2105 newTracks.push([]); 2106 } 2107 newTracks[targetTrack].push(event_1); 2108 } 2109 } 2110 return newTracks; 2111 } 2112 })(Midi); 2113 self.onmessage = async (e) => { 2114 try { 2115 const { trackId, midiBuffer } = e.data; 2116 const parsedMidi = new Midi.Midi(midiBuffer); 2117 const duration = parsedMidi.duration; 2118 const instruments = []; 2119 parsedMidi.tracks.forEach((track, i) => { 2120 instruments.push({ 2121 trackId: i, 2122 name: track.name || track.instrument.name || `Track ${i + 1}`, 2123 family: track.instrument.family, 2124 program: track.instrument.number !== void 0 ? track.instrument.number : 0, 2125 midiChannel: track.notes.length === 0 ? -1 : track.channel !== void 0 ? track.channel : 0, 2126 notesCount: track.notes.length 2127 }); 2128 }); 2129 const pianoRollData = []; 2130 let musicalTrackIdx = 0; 2131 parsedMidi.tracks.forEach((track, i) => { 2132 if (track.notes.length > 0) { 2133 track.notes.forEach((n) => { 2134 pianoRollData.push({ 2135 t: parseFloat(n.time.toFixed(3)), 2136 n: n.midi, 2137 d: parseFloat(n.duration.toFixed(3)), 2138 v: Math.round(n.velocity * 127), 2139 i: track.name || track.instrument.name || `Track ${i + 1}`, 2140 trackIdx: musicalTrackIdx, 2141 p: track.instrument.number !== void 0 ? track.instrument.number : 0, 2142 isDrum: track.instrument.family === "drums" 2143 }); 2144 }); 2145 musicalTrackIdx++; 2146 } 2147 }); 2148 const timeSignatures = parsedMidi.header.timeSignatures; 2149 const tempos = parsedMidi.header.tempos; 2150 const measureMap = []; 2151 let currentTick = 0; 2152 let currentTime = 0; 2153 if (timeSignatures && timeSignatures.length > 0) { 2154 measureMap.push({ time: 0, timeSignature: timeSignatures[0].timeSignature }); 2155 } 2156 let melodyTrackId = -1; 2157 let bassTrackId = -1; 2158 let highestAvgPitch = -1; 2159 let lowestAvgPitch = 999; 2160 parsedMidi.tracks.forEach((track, i) => { 2161 if (track.notes.length === 0 || track.instrument.family === "drums") return; 2162 let sumPitch = 0; 2163 track.notes.forEach((n) => sumPitch += n.midi); 2164 const avgPitch = sumPitch / track.notes.length; 2165 if (avgPitch > highestAvgPitch) { 2166 highestAvgPitch = avgPitch; 2167 melodyTrackId = i; 2168 } 2169 if (avgPitch < lowestAvgPitch) { 2170 lowestAvgPitch = avgPitch; 2171 bassTrackId = i; 2172 } 2173 }); 2174 const melodyDetection = { melodyTrackId, bassTrackId }; 2175 let intervals = []; 2176 let parsons = ""; 2177 if (melodyTrackId !== -1) { 2178 const melodyNotes = parsedMidi.tracks[melodyTrackId].notes.sort((a, b) => a.time - b.time); 2179 if (melodyNotes.length > 1) { 2180 parsons = "*"; 2181 for (let i = 1; i < Math.min(melodyNotes.length, 100); i++) { 2182 const prev = melodyNotes[i - 1].midi; 2183 const curr = melodyNotes[i].midi; 2184 const diff = curr - prev; 2185 intervals.push(diff); 2186 if (diff > 0) parsons += "U"; 2187 else if (diff < 0) parsons += "D"; 2188 else parsons += "R"; 2189 } 2190 } 2191 } 2192 let totalNotes = 0; 2193 let maxNotesPerSec = 0; 2194 parsedMidi.tracks.forEach((t) => totalNotes += t.notes.length); 2195 const notesPerSec = duration > 0 ? totalNotes / duration : 0; 2196 let difficulty = "Beginner"; 2197 if (notesPerSec > 15) difficulty = "Virtuoso"; 2198 else if (notesPerSec > 8) difficulty = "Advanced"; 2199 else if (notesPerSec > 4) difficulty = "Intermediate"; 2200 const majorProfile = [6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88]; 2201 const minorProfile = [6.33, 2.68, 3.52, 5.38, 2.6, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17]; 2202 const pitchClassDuration = new Array(12).fill(0); 2203 parsedMidi.tracks.forEach((track) => { 2204 if (track.instrument.family === "drums") return;
2205 track.notes.forEach((n) => { 2206 pitchClassDuration[n.midi % 12] += n.duration; 2207 }); 2208 }); 2209 let bestKey = "C Major"; 2210 let maxCorr = -Infinity; 2211 const keys = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; 2212 for (let i = 0; i < 12; i++) { 2213 let corrMaj = 0; 2214 let corrMin = 0; 2215 for (let j = 0; j < 12; j++) { 2216 corrMaj += pitchClassDuration[(i + j) % 12] * majorProfile[j]; 2217 corrMin += pitchClassDuration[(i + j) % 12] * minorProfile[j]; 2218 } 2219 if (corrMaj > maxCorr) { 2220 maxCorr = corrMaj; 2221 bestKey = keys[i] + " Major"; 2222 } 2223 if (corrMin > maxCorr) { 2224 maxCorr = corrMin; 2225 bestKey = keys[i] + " Minor"; 2226 } 2227 } 2228 let lyrics = []; 2229 if (parsedMidi.header.lyrics) { 2230 lyrics = parsedMidi.header.lyrics.map((l) => ({ time: l.time, text: l.text })); 2231 } 2232 self.postMessage({ 2233 trackId, 2234 status: "success", 2235 data: { 2236 instruments, 2237 duration, 2238 pianoRollData, 2239 measureMap, 2240 intervals, 2241 parsons, 2242 melodyDetection, 2243 bassDetection: { bassTrackId }, 2244 difficulty, 2245 rhythmFingerprint: null, 2246 // Placeholder for rhythm fingerprint 2247 keySignature: bestKey, 2248 lyrics 2249 } 2250 }); 2251 } catch (error) { 2252 self.postMessage({ 2253 status: "error", 2254 error: error.message 2255 }); 2256 } 2257 }; 2258})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.