@huffduff/midi-writer-ts 3.2.0 → 3.2.3

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 +10 -4
  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
package/src/vexflow.ts ADDED
@@ -0,0 +1,96 @@
1
+ import {NoteEvent} from './midi-events/note-event';
2
+ import {Track} from './chunks/track';
3
+
4
+ class VexFlow {
5
+
6
+ /**
7
+ * Support for converting VexFlow voice into MidiWriterJS track
8
+ * @return MidiWriter.Track object
9
+ */
10
+ trackFromVoice(voice, options = {addRenderedAccidentals: false}): Track {
11
+ const track = new Track;
12
+ let wait = [];
13
+
14
+ voice.tickables.forEach(tickable => {
15
+ if (tickable.noteType === 'n') {
16
+ track.addEvent(new NoteEvent({
17
+ pitch: tickable.keys.map((pitch, index) => this.convertPitch(pitch, index, tickable, options.addRenderedAccidentals)),
18
+ duration: this.convertDuration(tickable),
19
+ wait
20
+ }));
21
+ // reset wait
22
+ wait = [];
23
+ } else if (tickable.noteType === 'r') {
24
+ // move on to the next tickable and add this to the stack
25
+ // of the `wait` property for the next note event
26
+ wait.push(this.convertDuration(tickable));
27
+ }
28
+ });
29
+
30
+ // There may be outstanding rests at the end of the track,
31
+ // pad with a ghost note (zero duration and velocity), just to capture the wait.
32
+ if(wait.length > 0) {
33
+ track.addEvent(new NoteEvent({pitch: '[c4]', duration: '0', wait, velocity: '0'}));
34
+ }
35
+
36
+ return track;
37
+ }
38
+
39
+ /**
40
+ * Converts VexFlow pitch syntax to MidiWriterJS syntax
41
+ * @param pitch string
42
+ * @param index pitch index
43
+ * @param note struct from Vexflow
44
+ * @param addRenderedAccidentals adds Vexflow rendered accidentals
45
+ */
46
+ convertPitch(pitch, index, note, addRenderedAccidentals = false) {
47
+ // Splits note name from octave
48
+ const pitchParts = pitch.split('/');
49
+
50
+ // Retrieves accidentals from pitch
51
+ // Removes natural accidentals since they are not accepted in Tonal Midi
52
+ let accidentals = pitchParts[0].substring(1).replace('n', '');
53
+
54
+ if (addRenderedAccidentals) {
55
+ note.getAccidentals()?.forEach(accidental => {
56
+ if (accidental.index === index) {
57
+ if (accidental.type === 'n') {
58
+ accidentals = '';
59
+ } else {
60
+ accidentals += accidental.type;
61
+ }
62
+ }
63
+ });
64
+ }
65
+
66
+ return pitchParts[0][0] + accidentals + pitchParts[1];
67
+ }
68
+
69
+ /**
70
+ * Converts VexFlow duration syntax to MidiWriterJS syntax
71
+ * @param note struct from VexFlow
72
+ */
73
+ convertDuration(note) {
74
+ return 'd'.repeat(note.dots) + this.convertBaseDuration(note.duration) + (note.tuplet ? 't' + note.tuplet.num_notes : '');
75
+ }
76
+
77
+ /**
78
+ * Converts VexFlow base duration syntax to MidiWriterJS syntax
79
+ * @param duration Vexflow duration
80
+ * @returns MidiWriterJS duration
81
+ */
82
+ convertBaseDuration(duration: string): string {
83
+ switch (duration) {
84
+ case 'w':
85
+ return '1';
86
+ case 'h':
87
+ return '2';
88
+ case 'q':
89
+ return '4';
90
+ default:
91
+ return duration;
92
+ }
93
+ }
94
+ }
95
+
96
+ export {VexFlow};
package/src/writer.ts ADDED
@@ -0,0 +1,99 @@
1
+ import {Header} from './chunks/header';
2
+ import {Track} from './chunks/track';
3
+ import {Utils} from './utils';
4
+
5
+ /**
6
+ * Object that puts together tracks and provides methods for file output.
7
+ * @param {array|Track} tracks - A single {Track} object or an array of {Track} objects.
8
+ * @param {object} options - {middleC: 'C4'}
9
+ * @return {Writer}
10
+ */
11
+ class Writer {
12
+ tracks: Track[];
13
+ options: object;
14
+
15
+ constructor(tracks, options = {}) {
16
+ // Ensure tracks is an array
17
+ this.tracks = Utils.toArray(tracks);
18
+ this.options = options;
19
+ }
20
+
21
+ /**
22
+ * Builds array of data from chunkschunks.
23
+ * @return {array}
24
+ */
25
+ buildData() {
26
+ const data = [];
27
+ data.push(new Header(this.tracks.length))
28
+
29
+ // For each track add final end of track event and build data
30
+ this.tracks.forEach((track) => {
31
+ data.push(track.buildData(this.options));
32
+ });
33
+
34
+ return data;
35
+ }
36
+
37
+ /**
38
+ * Builds the file into a Uint8Array
39
+ * @return {Uint8Array}
40
+ */
41
+ buildFile(): Uint8Array {
42
+ let build = [];
43
+
44
+ // Data consists of chunks which consists of data
45
+ this.buildData().forEach((d) => build = build.concat(d.type, d.size, d.data));
46
+
47
+ return new Uint8Array(build);
48
+ }
49
+
50
+ /**
51
+ * Convert file buffer to a base64 string. Different methods depending on if browser or node.
52
+ * @return {string}
53
+ */
54
+ base64(): string {
55
+ if (typeof btoa === 'function') {
56
+ let binary = '';
57
+ const bytes = this.buildFile();
58
+ const len = bytes.byteLength;
59
+
60
+ for (let i = 0; i < len; i++) {
61
+ binary += String.fromCharCode(bytes[i]);
62
+ }
63
+
64
+ return btoa(binary);
65
+ }
66
+
67
+ return Buffer.from(this.buildFile()).toString('base64');
68
+ }
69
+
70
+ /**
71
+ * Get the data URI.
72
+ * @return {string}
73
+ */
74
+ dataUri(): string {
75
+ return 'data:audio/midi;base64,' + this.base64();
76
+ }
77
+
78
+
79
+ /**
80
+ * Set option on instantiated Writer.
81
+ * @param {string} key
82
+ * @param {any} value
83
+ * @return {Writer}
84
+ */
85
+ setOption(key: string, value: number|string): Writer {
86
+ this.options[key] = value;
87
+ return this;
88
+ }
89
+
90
+ /**
91
+ * Output to stdout
92
+ * @return {string}
93
+ */
94
+ stdout() {
95
+ return process.stdout.write(Buffer.from(this.buildFile()));
96
+ }
97
+ }
98
+
99
+ export {Writer};
package/.editorconfig DELETED
@@ -1,24 +0,0 @@
1
- # http://editorconfig.org
2
- root = true
3
-
4
- [*]
5
- charset = utf-8
6
- end_of_line = lf
7
- indent_size = 4
8
- indent_style = tab
9
- insert_final_newline = true
10
- trim_trailing_whitespace = true
11
-
12
- [*.json]
13
- insert_final_newline = false
14
- indent_size = 2
15
- indent_style = space
16
-
17
- [*.md]
18
- indent_size = 2
19
- indent_style = space
20
- trim_trailing_whitespace = false
21
-
22
- [*.yml]
23
- indent_size = 2
24
- indent_style = space
package/.eslintignore DELETED
@@ -1,3 +0,0 @@
1
- **/__tests__/**
2
- **/coverage/**
3
- **/node_modules/**
package/.eslintrc.js DELETED
@@ -1,18 +0,0 @@
1
- module.exports = {
2
- "env": {
3
- "browser": true,
4
- "es6": true,
5
- "node": true
6
- },
7
- "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
8
- "parser": '@typescript-eslint/parser',
9
- "plugins": ['@typescript-eslint'],
10
- "globals": {
11
- "Atomics": "readonly",
12
- "SharedArrayBuffer": "readonly"
13
- },
14
- "parserOptions": {
15
- "ecmaVersion": 2020,
16
- "sourceType": "module"
17
- }
18
- };
package/.nvmrc DELETED
@@ -1 +0,0 @@
1
- v18.14.2
package/.travis.yml DELETED
@@ -1,3 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "stable"