@huffduff/midi-writer-ts 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +27 -28
  2. package/build/index.cjs +24 -26
  3. package/build/index.mjs +1 -26
  4. package/build/types/main.d.ts +2 -35
  5. package/package.json +9 -2
  6. package/src/abstract-event.ts +8 -0
  7. package/src/chunks/chunk.ts +6 -0
  8. package/src/chunks/header.ts +29 -0
  9. package/src/chunks/track.ts +345 -0
  10. package/src/constants.ts +18 -0
  11. package/src/main.ts +48 -0
  12. package/src/meta-events/copyright-event.ts +35 -0
  13. package/src/meta-events/cue-point-event.ts +35 -0
  14. package/src/meta-events/end-track-event.ts +29 -0
  15. package/src/meta-events/instrument-name-event.ts +35 -0
  16. package/src/meta-events/key-signature-event.ts +73 -0
  17. package/src/meta-events/lyric-event.ts +35 -0
  18. package/src/meta-events/marker-event.ts +35 -0
  19. package/src/meta-events/meta-event.ts +7 -0
  20. package/src/meta-events/tempo-event.ts +37 -0
  21. package/src/meta-events/text-event.ts +35 -0
  22. package/src/meta-events/time-signature-event.ts +32 -0
  23. package/src/meta-events/track-name-event.ts +35 -0
  24. package/src/midi-events/controller-change-event.ts +30 -0
  25. package/src/midi-events/midi-event.ts +11 -0
  26. package/src/midi-events/note-event.ts +164 -0
  27. package/src/midi-events/note-off-event.ts +55 -0
  28. package/src/midi-events/note-on-event.ts +69 -0
  29. package/src/midi-events/pitch-bend-event.ts +40 -0
  30. package/src/midi-events/program-change-event.ts +28 -0
  31. package/src/utils.ts +263 -0
  32. package/src/vexflow.ts +96 -0
  33. package/src/writer.ts +99 -0
  34. package/.editorconfig +0 -24
  35. package/.eslintignore +0 -3
  36. package/.eslintrc.js +0 -18
  37. package/.nvmrc +0 -1
  38. package/.travis.yml +0 -3
  39. package/browser/midiwriter.js +0 -1367
  40. package/jsdoc.json +0 -5
  41. package/postinstall.js +0 -1
  42. package/rollup.config.js +0 -22
  43. package/runkit.js +0 -18
  44. package/tsconfig.json +0 -13
  45. package/typedoc.json +0 -5
@@ -0,0 +1,18 @@
1
+ /**
2
+ * MIDI file format constants.
3
+ * @return {Constants}
4
+ */
5
+
6
+ const Constants = {
7
+ VERSION : '3.1.1',
8
+ HEADER_CHUNK_TYPE : [0x4d, 0x54, 0x68, 0x64], // Mthd
9
+ HEADER_CHUNK_LENGTH : [0x00, 0x00, 0x00, 0x06], // Header size for SMF
10
+ HEADER_CHUNK_FORMAT0 : [0x00, 0x00], // Midi Type 0 id
11
+ HEADER_CHUNK_FORMAT1 : [0x00, 0x01], // Midi Type 1 id
12
+ HEADER_CHUNK_DIVISION : [0x00, 0x80], // Defaults to 128 ticks per beat
13
+ TRACK_CHUNK_TYPE : [0x4d, 0x54, 0x72, 0x6b], // MTrk,
14
+ META_EVENT_ID : 0xFF,
15
+ META_SMTPE_OFFSET : 0x54
16
+ };
17
+
18
+ export {Constants};
package/src/main.ts ADDED
@@ -0,0 +1,48 @@
1
+
2
+ import { Constants } from './constants';
3
+ import { ControllerChangeEvent } from './midi-events/controller-change-event';
4
+ import { CopyrightEvent } from './meta-events/copyright-event';
5
+ import { CuePointEvent } from './meta-events/cue-point-event';
6
+ import { EndTrackEvent } from './meta-events/end-track-event';
7
+ import { InstrumentNameEvent } from './meta-events/instrument-name-event';
8
+ import { KeySignatureEvent } from './meta-events/key-signature-event';
9
+ import { LyricEvent } from './meta-events/lyric-event';
10
+ import { MarkerEvent } from './meta-events/marker-event';
11
+ import { NoteOnEvent } from './midi-events/note-on-event';
12
+ import { NoteOffEvent } from './midi-events/note-off-event';
13
+ import { NoteEvent } from './midi-events/note-event';
14
+ import { PitchBendEvent } from './midi-events/pitch-bend-event';
15
+ import { ProgramChangeEvent } from './midi-events/program-change-event';
16
+ import { TempoEvent } from './meta-events/tempo-event';
17
+ import { TextEvent } from './meta-events/text-event';
18
+ import { TimeSignatureEvent } from './meta-events/time-signature-event';
19
+ import { Track } from './chunks/track';
20
+ import { TrackNameEvent } from './meta-events/track-name-event';
21
+ import { Utils } from './utils';
22
+ import { VexFlow } from './vexflow';
23
+ import { Writer } from './writer';
24
+
25
+ export {
26
+ Constants,
27
+ ControllerChangeEvent,
28
+ CopyrightEvent,
29
+ CuePointEvent,
30
+ EndTrackEvent,
31
+ InstrumentNameEvent,
32
+ KeySignatureEvent,
33
+ LyricEvent,
34
+ MarkerEvent,
35
+ NoteOnEvent,
36
+ NoteOffEvent,
37
+ NoteEvent,
38
+ PitchBendEvent,
39
+ ProgramChangeEvent,
40
+ TempoEvent,
41
+ TextEvent,
42
+ TimeSignatureEvent,
43
+ Track,
44
+ TrackNameEvent,
45
+ Utils,
46
+ VexFlow,
47
+ Writer
48
+ };
@@ -0,0 +1,35 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a tempo meta event.
7
+ * @param {object} fields {text: string, delta: integer}
8
+ * @return {CopyrightEvent}
9
+ */
10
+ class CopyrightEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ text: string;
15
+ type: 0x02;
16
+
17
+ constructor(fields: { text: string; delta?: number; }) {
18
+ this.delta = fields.delta || 0x00;
19
+ this.name = 'CopyrightEvent';
20
+ this.text = fields.text;
21
+ this.type = 0x02;
22
+
23
+ const textBytes = Utils.stringToBytes(this.text);
24
+
25
+ // Start with zero time delta
26
+ this.data = Utils.numberToVariableLength(this.delta).concat(
27
+ Constants.META_EVENT_ID,
28
+ this.type,
29
+ Utils.numberToVariableLength(textBytes.length), // Size
30
+ textBytes, // Text
31
+ );
32
+ }
33
+ }
34
+
35
+ export {CopyrightEvent};
@@ -0,0 +1,35 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a cue point meta event.
7
+ * @param {object} fields {text: string, delta: integer}
8
+ * @return {CuePointEvent}
9
+ */
10
+ class CuePointEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ text: string;
15
+ type: 0x07;
16
+
17
+ constructor(fields: { text: string; delta?: number; }) {
18
+ this.delta = fields.delta || 0x00;
19
+ this.name = 'CuePointEvent';
20
+ this.text = fields.text;
21
+ this.type = 0x07;
22
+
23
+ const textBytes = Utils.stringToBytes(this.text);
24
+
25
+ // Start with zero time delta
26
+ this.data = Utils.numberToVariableLength(this.delta).concat(
27
+ Constants.META_EVENT_ID,
28
+ this.type,
29
+ Utils.numberToVariableLength(textBytes.length), // Size
30
+ textBytes, // Text
31
+ );
32
+ }
33
+ }
34
+
35
+ export {CuePointEvent};
@@ -0,0 +1,29 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a end track meta event.
7
+ * @param {object} fields {delta: integer}
8
+ * @return {EndTrackEvent}
9
+ */
10
+ class EndTrackEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ type: [0x2F, 0x00];
15
+
16
+ constructor(fields?: { delta: number; }) {
17
+ this.delta = fields?.delta || 0x00;
18
+ this.name = 'EndTrackEvent';
19
+ this.type = [0x2F, 0x00];
20
+
21
+ // Start with zero time delta
22
+ this.data = Utils.numberToVariableLength(this.delta).concat(
23
+ Constants.META_EVENT_ID,
24
+ this.type
25
+ );
26
+ }
27
+ }
28
+
29
+ export {EndTrackEvent};
@@ -0,0 +1,35 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of an instrument name meta event.
7
+ * @param {object} fields {text: string, delta: integer}
8
+ * @return {InstrumentNameEvent}
9
+ */
10
+ class InstrumentNameEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ text: string;
15
+ type: 0x04;
16
+
17
+ constructor(fields: { text: string; delta?: number; }) {
18
+ this.delta = fields.delta || 0x00;
19
+ this.name = 'InstrumentNameEvent';
20
+ this.text = fields.text;
21
+ this.type = 0x04;
22
+
23
+ const textBytes = Utils.stringToBytes(this.text);
24
+
25
+ // Start with zero time delta
26
+ this.data = Utils.numberToVariableLength(this.delta).concat(
27
+ Constants.META_EVENT_ID,
28
+ this.type,
29
+ Utils.numberToVariableLength(textBytes.length), // Size
30
+ textBytes, // Instrument name
31
+ );
32
+ }
33
+ }
34
+
35
+ export {InstrumentNameEvent};
@@ -0,0 +1,73 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a key signature meta event.
7
+ * @return {KeySignatureEvent}
8
+ */
9
+ class KeySignatureEvent implements MetaEvent {
10
+ data: number[];
11
+ delta: number;
12
+ name: string;
13
+ type: 0x59;
14
+
15
+ constructor(sf, mi) {
16
+ this.name = 'KeySignatureEvent';
17
+ this.type = 0x59;
18
+
19
+ let mode = mi || 0;
20
+ sf = sf || 0;
21
+
22
+ // Function called with string notation
23
+ if (typeof mi === 'undefined') {
24
+ const fifths = [
25
+ ['Cb', 'Gb', 'Db', 'Ab', 'Eb', 'Bb', 'F', 'C', 'G', 'D', 'A', 'E', 'B', 'F#', 'C#'],
26
+ ['ab', 'eb', 'bb', 'f', 'c', 'g', 'd', 'a', 'e', 'b', 'f#', 'c#', 'g#', 'd#', 'a#']
27
+ ];
28
+ const _sflen = sf.length;
29
+ let note = sf || 'C';
30
+
31
+ if (sf[0] === sf[0].toLowerCase()) mode = 1
32
+
33
+ if (_sflen > 1) {
34
+ switch (sf.charAt(_sflen - 1)) {
35
+ case 'm':
36
+ mode = 1;
37
+ note = sf.charAt(0).toLowerCase();
38
+ note = note.concat(sf.substring(1, _sflen - 1));
39
+ break;
40
+ case '-':
41
+ mode = 1;
42
+ note = sf.charAt(0).toLowerCase();
43
+ note = note.concat(sf.substring(1, _sflen - 1));
44
+ break;
45
+ case 'M':
46
+ mode = 0;
47
+ note = sf.charAt(0).toUpperCase();
48
+ note = note.concat(sf.substring(1, _sflen - 1));
49
+ break;
50
+ case '+':
51
+ mode = 0;
52
+ note = sf.charAt(0).toUpperCase();
53
+ note = note.concat(sf.substring(1, _sflen - 1));
54
+ break;
55
+ }
56
+ }
57
+
58
+ const fifthindex = fifths[mode].indexOf(note);
59
+ sf = fifthindex === -1 ? 0 : fifthindex - 7;
60
+ }
61
+
62
+ // Start with zero time delta
63
+ this.data = Utils.numberToVariableLength(0x00).concat(
64
+ Constants.META_EVENT_ID,
65
+ this.type,
66
+ [0x02], // Size
67
+ Utils.numberToBytes(sf, 1), // Number of sharp or flats ( < 0 flat; > 0 sharp)
68
+ Utils.numberToBytes(mode, 1), // Mode: 0 major, 1 minor
69
+ );
70
+ }
71
+ }
72
+
73
+ export {KeySignatureEvent};
@@ -0,0 +1,35 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a lyric meta event.
7
+ * @param {object} fields {text: string, delta: integer}
8
+ * @return {LyricEvent}
9
+ */
10
+ class LyricEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ text: string;
15
+ type: 0x05;
16
+
17
+ constructor(fields: { text: string; delta?: number; }) {
18
+ this.delta = fields.delta || 0x00;
19
+ this.name = 'LyricEvent';
20
+ this.text = fields.text;
21
+ this.type = 0x05;
22
+
23
+ const textBytes = Utils.stringToBytes(this.text);
24
+
25
+ // Start with zero time delta
26
+ this.data = Utils.numberToVariableLength(this.delta).concat(
27
+ Constants.META_EVENT_ID,
28
+ this.type,
29
+ Utils.numberToVariableLength(textBytes.length), // Size
30
+ textBytes, // Text
31
+ );
32
+ }
33
+ }
34
+
35
+ export {LyricEvent};
@@ -0,0 +1,35 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a marker meta event.
7
+ * @param {object} fields {text: string, delta: integer}
8
+ * @return {MarkerEvent}
9
+ */
10
+ class MarkerEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ text: string;
15
+ type: 0x06;
16
+
17
+ constructor(fields: { text: string; delta?: number; }) {
18
+ this.delta = fields.delta || 0x00;
19
+ this.name = 'MarkerEvent';
20
+ this.text = fields.text;
21
+ this.type = 0x06;
22
+
23
+ const textBytes = Utils.stringToBytes(this.text);
24
+
25
+ // Start with zero time delta
26
+ this.data = Utils.numberToVariableLength(this.delta).concat(
27
+ Constants.META_EVENT_ID,
28
+ this.type,
29
+ Utils.numberToVariableLength(textBytes.length), // Size
30
+ textBytes, // Text
31
+ );
32
+ }
33
+ }
34
+
35
+ export {MarkerEvent};
@@ -0,0 +1,7 @@
1
+ import { AbstractEvent } from "../abstract-event";
2
+
3
+ interface MetaEvent extends AbstractEvent {
4
+ type: number|number[];
5
+ }
6
+
7
+ export {MetaEvent};
@@ -0,0 +1,37 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a tempo meta event.
7
+ * @param {object} fields {bpm: integer, delta: integer}
8
+ * @return {TempoEvent}
9
+ */
10
+ class TempoEvent implements MetaEvent {
11
+ bpm: number;
12
+ data: number[];
13
+ delta: number;
14
+ name: string;
15
+ tick: number;
16
+ type: 0x51;
17
+
18
+ constructor(fields: { bpm: number; tick?: number; delta?: number; }) {
19
+ this.bpm = fields.bpm;
20
+ this.delta = fields.delta || 0x00;
21
+ this.tick = fields.tick;
22
+ this.name = 'TempoEvent';
23
+ this.type = 0x51;
24
+
25
+ const tempo = Math.round(60000000 / this.bpm);
26
+
27
+ // Start with zero time delta
28
+ this.data = Utils.numberToVariableLength(this.delta).concat(
29
+ Constants.META_EVENT_ID,
30
+ this.type,
31
+ [0x03], // Size
32
+ Utils.numberToBytes(tempo, 3), // Tempo, 3 bytes
33
+ );
34
+ }
35
+ }
36
+
37
+ export {TempoEvent};
@@ -0,0 +1,35 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a tempo meta event.
7
+ * @param {object} fields {text: string, delta: integer}
8
+ * @return {TextEvent}
9
+ */
10
+ class TextEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ text: string;
15
+ type: 0x01;
16
+
17
+ constructor(fields: { text: string; delta?: number; }) {
18
+ this.delta = fields.delta || 0x00;
19
+ this.text = fields.text;
20
+ this.name = 'TextEvent';
21
+ this.type = 0x01;
22
+
23
+ const textBytes = Utils.stringToBytes(this.text);
24
+
25
+ // Start with zero time delta
26
+ this.data = Utils.numberToVariableLength(fields.delta).concat(
27
+ Constants.META_EVENT_ID,
28
+ this.type,
29
+ Utils.numberToVariableLength(textBytes.length), // Size
30
+ textBytes, // Text
31
+ );
32
+ }
33
+ }
34
+
35
+ export {TextEvent};
@@ -0,0 +1,32 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a time signature meta event.
7
+ * @return {TimeSignatureEvent}
8
+ */
9
+ class TimeSignatureEvent implements MetaEvent {
10
+ data: number[];
11
+ delta: number;
12
+ name: string;
13
+ type: 0x58;
14
+
15
+ constructor(numerator, denominator, midiclockspertick, notespermidiclock) {
16
+ this.name = 'TimeSignatureEvent';
17
+ this.type = 0x58;
18
+
19
+ // Start with zero time delta
20
+ this.data = Utils.numberToVariableLength(0x00).concat(
21
+ Constants.META_EVENT_ID,
22
+ this.type,
23
+ [0x04], // Size
24
+ Utils.numberToBytes(numerator, 1), // Numerator, 1 bytes
25
+ Utils.numberToBytes(Math.log2(denominator), 1), // Denominator is expressed as pow of 2, 1 bytes
26
+ Utils.numberToBytes(midiclockspertick || 24, 1), // MIDI Clocks per tick, 1 bytes
27
+ Utils.numberToBytes(notespermidiclock || 8, 1), // Number of 1/32 notes per MIDI clocks, 1 bytes
28
+ );
29
+ }
30
+ }
31
+
32
+ export {TimeSignatureEvent};
@@ -0,0 +1,35 @@
1
+ import {Constants} from '../constants';
2
+ import {MetaEvent} from './meta-event';
3
+ import {Utils} from '../utils';
4
+
5
+ /**
6
+ * Object representation of a tempo meta event.
7
+ * @param {object} fields {text: string, delta: integer}
8
+ * @return {TrackNameEvent}
9
+ */
10
+ class TrackNameEvent implements MetaEvent {
11
+ data: number[];
12
+ delta: number;
13
+ name: string;
14
+ text: string;
15
+ type: 0x03;
16
+
17
+ constructor(fields: { text: string; delta?: number; }) {
18
+ this.delta = fields.delta || 0x00;
19
+ this.name = 'TrackNameEvent';
20
+ this.text = fields.text;
21
+ this.type = 0x03;
22
+
23
+ const textBytes = Utils.stringToBytes(this.text);
24
+
25
+ // Start with zero time delta
26
+ this.data = Utils.numberToVariableLength(this.delta).concat(
27
+ Constants.META_EVENT_ID,
28
+ this.type,
29
+ Utils.numberToVariableLength(textBytes.length), // Size
30
+ textBytes, // Text
31
+ );
32
+ }
33
+ }
34
+
35
+ export {TrackNameEvent};
@@ -0,0 +1,30 @@
1
+ import {MidiEvent} from './midi-event';
2
+ import {Utils} from '../utils';
3
+
4
+ /**
5
+ * Holds all data for a "controller change" MIDI event
6
+ * @param {object} fields {controllerNumber: integer, controllerValue: integer, delta: integer}
7
+ * @return {ControllerChangeEvent}
8
+ */
9
+ class ControllerChangeEvent implements MidiEvent {
10
+ channel: number;
11
+ controllerNumber: number;
12
+ controllerValue: number;
13
+ data: number[];
14
+ delta: number;
15
+ name: string;
16
+ status: 0xB0;
17
+
18
+ constructor(fields: { controllerNumber: number; controllerValue: number; channel?: number; delta?: number; }) {
19
+ this.channel = fields.channel - 1 || 0;
20
+ this.controllerValue = fields.controllerValue;
21
+ this.controllerNumber = fields.controllerNumber;
22
+ this.delta = fields.delta || 0x00;
23
+ this.name = 'ControllerChangeEvent';
24
+ this.status = 0xB0;
25
+
26
+ this.data = Utils.numberToVariableLength(fields.delta).concat(this.status | this.channel, this.controllerNumber, this.controllerValue);
27
+ }
28
+ }
29
+
30
+ export {ControllerChangeEvent};
@@ -0,0 +1,11 @@
1
+ import {AbstractEvent} from '../abstract-event';
2
+
3
+
4
+ interface MidiEvent extends AbstractEvent {
5
+ channel: number;
6
+ status: number;
7
+ // eslint-disable-next-line @typescript-eslint/ban-types
8
+ buildData?: Function;
9
+ }
10
+
11
+ export {MidiEvent};