@marmooo/midi-player 0.0.2 → 0.0.4

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.
package/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  ## Demo
7
7
 
8
8
  - [Basic usage](https://marmooo.github.io/midi-player/)
9
+ - [Humidy](https://marmooo.github.io/humidy/) - GM2 MIDI mixer app
9
10
 
10
11
  ## Usage
11
12
 
@@ -58,7 +59,7 @@ but you can also set it as follows.
58
59
 
59
60
  ```
60
61
  const midiPlayer = new MIDIPlayer(midy);
61
- midiPlayer.soundFontURL = "https://soundfonts.pages.dev/SGM-V2.01";
62
+ midiPlayer.soundFontURL = "https://soundfonts.pages.dev/GeneralUser_GS_v1.471";
62
63
  ```
63
64
 
64
65
  ```
@@ -12,6 +12,11 @@ export class MIDIPlayer {
12
12
  pauseNode: any;
13
13
  resumeNode: any;
14
14
  stopNode: any;
15
+ isPlaying: boolean;
16
+ isPausing: boolean;
17
+ isPaused: boolean;
18
+ isStopping: boolean;
19
+ isSeeking: boolean;
15
20
  root: any;
16
21
  defaultLayout(): void;
17
22
  row(): any;
@@ -20,6 +25,7 @@ export class MIDIPlayer {
20
25
  formRange(title: any, className: any, value: any, display: any): any;
21
26
  text(text: any, className: any): any;
22
27
  startTimer(): void;
28
+ stopTimer(): void;
23
29
  loadMIDI(file: any): Promise<void>;
24
30
  setSoundFontDir(dir: any): void;
25
31
  getSoundFontPaths(): string[];
@@ -27,7 +33,7 @@ export class MIDIPlayer {
27
33
  handleStop(): Promise<void>;
28
34
  stop(): any;
29
35
  handlePlay(): Promise<void>;
30
- handlePause(): void;
36
+ handlePause(): Promise<void>;
31
37
  handleResume(): Promise<void>;
32
38
  playPauseResume(): any;
33
39
  volumeText(): any;
@@ -1 +1 @@
1
- {"version":3,"file":"midi-player.d.ts","sourceRoot":"","sources":["../src/midi-player.js"],"names":[],"mappings":"AAAA;IAcE,uBAGC;IAhBD,qBAAoE;IACpE,UAAK;IACL,WAAM;IACN,oBAAgB;IAChB,yBAAuB;IACvB,kBAAa;IACb,mBAAc;IACd,iBAAY;IACZ,cAAS;IACT,eAAU;IACV,gBAAW;IACX,cAAS;IAIP,UAAiD;IAGnD,sBAMC;IAED,WAOC;IAED,iCASC;IAED,qEASC;IAED,qEAOC;IAED,qCAKC;IAED,mBAYC;IAED,mCAKC;IAED,gCAEC;IAED,8BAcC;IAED,uBAaC;IAED,4BAQC;IAED,YAKC;IAED,4BAUC;IAED,oBAOC;IAED,8BAYC;IAED,uBA2BC;IAED,kBAEC;IAED,cAwCC;IAED,eAgBC;IAED,gBAIC;IAED,iBAIC;IAED,yBAWC;CACF"}
1
+ {"version":3,"file":"midi-player.d.ts","sourceRoot":"","sources":["../src/midi-player.js"],"names":[],"mappings":"AAAA;IAmBE,uBAGC;IArBD,qBAAoE;IACpE,UAAK;IACL,WAAM;IACN,oBAAgB;IAChB,yBAAuB;IACvB,kBAAa;IACb,mBAAc;IACd,iBAAY;IACZ,cAAS;IACT,eAAU;IACV,gBAAW;IACX,cAAS;IACT,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAIhB,UAAiD;IAGnD,sBAMC;IAED,WAOC;IAED,iCASC;IAED,qEASC;IAED,qEAOC;IAED,qCAKC;IAED,mBAeC;IAED,kBAKC;IAED,mCAKC;IAED,gCAEC;IAED,8BAaC;IAED,uBAYC;IAED,4BAUC;IAED,YAKC;IAED,4BAYC;IAED,6BAUC;IAED,8BAcC;IAED,uBA2BC;IAED,kBAEC;IAED,cAwCC;IAED,eAkBC;IAED,gBAIC;IAED,iBAIC;IAED,yBAWC;CACF"}
@@ -72,6 +72,36 @@ export class MIDIPlayer {
72
72
  writable: true,
73
73
  value: void 0
74
74
  });
75
+ Object.defineProperty(this, "isPlaying", {
76
+ enumerable: true,
77
+ configurable: true,
78
+ writable: true,
79
+ value: false
80
+ });
81
+ Object.defineProperty(this, "isPausing", {
82
+ enumerable: true,
83
+ configurable: true,
84
+ writable: true,
85
+ value: false
86
+ });
87
+ Object.defineProperty(this, "isPaused", {
88
+ enumerable: true,
89
+ configurable: true,
90
+ writable: true,
91
+ value: false
92
+ });
93
+ Object.defineProperty(this, "isStopping", {
94
+ enumerable: true,
95
+ configurable: true,
96
+ writable: true,
97
+ value: false
98
+ });
99
+ Object.defineProperty(this, "isSeeking", {
100
+ enumerable: true,
101
+ configurable: true,
102
+ writable: true,
103
+ value: false
104
+ });
75
105
  this.midy = midy;
76
106
  this.root = document.createElement("midi-player");
77
107
  }
@@ -126,16 +156,25 @@ export class MIDIPlayer {
126
156
  }
127
157
  startTimer() {
128
158
  const endTime = this.midy.totalTime;
129
- this.timer = setInterval(() => {
159
+ this.stopTimer();
160
+ const update = () => {
130
161
  const now = this.midy.currentTime();
131
- const seconds = Math.ceil(now);
132
162
  if (this.currTimeNode) {
163
+ const seconds = Math.ceil(now);
133
164
  this.currTimeNode.textContent = this.formatTime(seconds);
134
165
  }
135
166
  if (this.seekBarNode) {
136
167
  this.seekBarNode.value = now / endTime;
137
168
  }
138
- }, this.currTimeInterval);
169
+ this.timer = requestAnimationFrame(update);
170
+ };
171
+ this.timer = requestAnimationFrame(update);
172
+ }
173
+ stopTimer() {
174
+ if (this.timer) {
175
+ cancelAnimationFrame(this.timer);
176
+ this.timer = null;
177
+ }
139
178
  }
140
179
  async loadMIDI(file) {
141
180
  await this.midy.loadMIDI(file);
@@ -150,27 +189,25 @@ export class MIDIPlayer {
150
189
  const paths = [];
151
190
  const { midy, soundFontURL } = this;
152
191
  for (const instrument of midy.instruments) {
153
- const [bankNumber, programNumber] = instrument.split(":").map(Number);
154
- const table = midy.soundFontTable[programNumber];
155
- if (table.has(bankNumber))
192
+ const [bank, program] = instrument.split(":");
193
+ const bankNumber = Number(bank);
194
+ const programNumber = Number(program);
195
+ const index = midy.soundFontTable[programNumber][bankNumber];
196
+ if (index !== undefined)
156
197
  continue;
157
- const program = programNumber.toString().padStart(3, "0");
158
- const path = bankNumber === 128
159
- ? `${soundFontURL}/128.sf3`
160
- : `${soundFontURL}/${program}.sf3`;
161
- paths.push(path);
198
+ const baseName = bankNumber === 128 ? "128" : program;
199
+ paths.push(`${soundFontURL}/${baseName}.sf3`);
162
200
  }
163
201
  return paths;
164
202
  }
165
203
  async start() {
204
+ this.isPlaying = true;
166
205
  const midy = this.midy;
167
- if (midy.soundFonts.length === 0) {
168
- const paths = this.getSoundFontPaths();
169
- await midy.loadSoundFont(paths);
170
- }
206
+ await midy.loadSoundFont(this.getSoundFontPaths());
171
207
  this.startTimer();
172
208
  await midy.start();
173
- clearInterval(this.timer);
209
+ this.stopTimer();
210
+ this.isPlaying = false;
174
211
  if (!midy.isPaused && this.currTimeNode) {
175
212
  this.currTimeNode.textContent = "0:00";
176
213
  this.seekBarNode.value = 0;
@@ -180,11 +217,13 @@ export class MIDIPlayer {
180
217
  const midy = this.midy;
181
218
  if (!midy.isPlaying)
182
219
  return;
183
- clearInterval(this.timer);
220
+ this.isStopping = true;
184
221
  this.playNode.style.display = "initial";
185
222
  this.pauseNode.style.display = "none";
186
223
  this.resumeNode.style.display = "none";
224
+ this.stopTimer();
187
225
  await midy.stop();
226
+ this.isPlaying = false;
188
227
  }
189
228
  stop() {
190
229
  const stop = this.button("start", "midi-player-start", "stop", "initial");
@@ -196,32 +235,39 @@ export class MIDIPlayer {
196
235
  const { midy, playNode, pauseNode } = this;
197
236
  if (midy.isPlaying || midy.isPaused)
198
237
  return;
238
+ this.isPlaying = true;
199
239
  playNode.style.display = "none";
200
240
  pauseNode.style.display = "initial";
201
241
  await this.start();
242
+ this.isPlaying = false;
202
243
  if (!midy.isPaused) {
203
244
  pauseNode.style.display = "none";
204
245
  playNode.style.display = "initial";
205
246
  }
206
247
  }
207
- handlePause() {
248
+ async handlePause() {
208
249
  const midy = this.midy;
209
250
  if (!midy.isPlaying || midy.isPaused)
210
251
  return;
252
+ this.isPausing = true;
211
253
  this.pauseNode.style.display = "none";
212
254
  this.resumeNode.style.display = "initial";
213
- clearInterval(this.timer);
214
- midy.pause();
255
+ this.stopTimer();
256
+ await midy.pause();
257
+ this.isPausing = false;
258
+ this.isPaused = true;
215
259
  }
216
260
  async handleResume() {
217
261
  const { midy, playNode, pauseNode, resumeNode } = this;
218
262
  if (!midy.isPaused)
219
263
  return;
264
+ this.isPlaying = true;
220
265
  pauseNode.style.display = "initial";
221
266
  resumeNode.style.display = "none";
222
267
  this.startTimer();
223
268
  await midy.resume();
224
- clearInterval(this.timer);
269
+ this.stopTimer();
270
+ this.isPlaying = false;
225
271
  if (!midy.isPaused) {
226
272
  pauseNode.style.display = "none";
227
273
  playNode.style.display = "initial";
@@ -282,11 +328,13 @@ export class MIDIPlayer {
282
328
  seekBar() {
283
329
  const seekBar = this.formRange("playback position", "midi-player-seekBar", 0, "initial");
284
330
  seekBar.oninput = (event) => {
331
+ this.isSeeking = true;
285
332
  const time = event.target.value * this.midy.totalTime;
286
333
  this.midy.seekTo(time);
287
334
  if (this.currTimeNode) {
288
335
  this.currTimeNode.textContent = this.formatTime(time);
289
336
  }
337
+ this.isSeeking = false;
290
338
  };
291
339
  this.seekBarNode = seekBar;
292
340
  return seekBar;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marmooo/midi-player",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "<midi-player> HTML elements powered by Midy.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,6 +12,11 @@ export class MIDIPlayer {
12
12
  pauseNode: any;
13
13
  resumeNode: any;
14
14
  stopNode: any;
15
+ isPlaying: boolean;
16
+ isPausing: boolean;
17
+ isPaused: boolean;
18
+ isStopping: boolean;
19
+ isSeeking: boolean;
15
20
  root: any;
16
21
  defaultLayout(): void;
17
22
  row(): any;
@@ -20,6 +25,7 @@ export class MIDIPlayer {
20
25
  formRange(title: any, className: any, value: any, display: any): any;
21
26
  text(text: any, className: any): any;
22
27
  startTimer(): void;
28
+ stopTimer(): void;
23
29
  loadMIDI(file: any): Promise<void>;
24
30
  setSoundFontDir(dir: any): void;
25
31
  getSoundFontPaths(): string[];
@@ -27,7 +33,7 @@ export class MIDIPlayer {
27
33
  handleStop(): Promise<void>;
28
34
  stop(): any;
29
35
  handlePlay(): Promise<void>;
30
- handlePause(): void;
36
+ handlePause(): Promise<void>;
31
37
  handleResume(): Promise<void>;
32
38
  playPauseResume(): any;
33
39
  volumeText(): any;
@@ -1 +1 @@
1
- {"version":3,"file":"midi-player.d.ts","sourceRoot":"","sources":["../src/midi-player.js"],"names":[],"mappings":"AAAA;IAcE,uBAGC;IAhBD,qBAAoE;IACpE,UAAK;IACL,WAAM;IACN,oBAAgB;IAChB,yBAAuB;IACvB,kBAAa;IACb,mBAAc;IACd,iBAAY;IACZ,cAAS;IACT,eAAU;IACV,gBAAW;IACX,cAAS;IAIP,UAAiD;IAGnD,sBAMC;IAED,WAOC;IAED,iCASC;IAED,qEASC;IAED,qEAOC;IAED,qCAKC;IAED,mBAYC;IAED,mCAKC;IAED,gCAEC;IAED,8BAcC;IAED,uBAaC;IAED,4BAQC;IAED,YAKC;IAED,4BAUC;IAED,oBAOC;IAED,8BAYC;IAED,uBA2BC;IAED,kBAEC;IAED,cAwCC;IAED,eAgBC;IAED,gBAIC;IAED,iBAIC;IAED,yBAWC;CACF"}
1
+ {"version":3,"file":"midi-player.d.ts","sourceRoot":"","sources":["../src/midi-player.js"],"names":[],"mappings":"AAAA;IAmBE,uBAGC;IArBD,qBAAoE;IACpE,UAAK;IACL,WAAM;IACN,oBAAgB;IAChB,yBAAuB;IACvB,kBAAa;IACb,mBAAc;IACd,iBAAY;IACZ,cAAS;IACT,eAAU;IACV,gBAAW;IACX,cAAS;IACT,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAIhB,UAAiD;IAGnD,sBAMC;IAED,WAOC;IAED,iCASC;IAED,qEASC;IAED,qEAOC;IAED,qCAKC;IAED,mBAeC;IAED,kBAKC;IAED,mCAKC;IAED,gCAEC;IAED,8BAaC;IAED,uBAYC;IAED,4BAUC;IAED,YAKC;IAED,4BAYC;IAED,6BAUC;IAED,8BAcC;IAED,uBA2BC;IAED,kBAEC;IAED,cAwCC;IAED,eAkBC;IAED,gBAIC;IAED,iBAIC;IAED,yBAWC;CACF"}
@@ -75,6 +75,36 @@ class MIDIPlayer {
75
75
  writable: true,
76
76
  value: void 0
77
77
  });
78
+ Object.defineProperty(this, "isPlaying", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: false
83
+ });
84
+ Object.defineProperty(this, "isPausing", {
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true,
88
+ value: false
89
+ });
90
+ Object.defineProperty(this, "isPaused", {
91
+ enumerable: true,
92
+ configurable: true,
93
+ writable: true,
94
+ value: false
95
+ });
96
+ Object.defineProperty(this, "isStopping", {
97
+ enumerable: true,
98
+ configurable: true,
99
+ writable: true,
100
+ value: false
101
+ });
102
+ Object.defineProperty(this, "isSeeking", {
103
+ enumerable: true,
104
+ configurable: true,
105
+ writable: true,
106
+ value: false
107
+ });
78
108
  this.midy = midy;
79
109
  this.root = document.createElement("midi-player");
80
110
  }
@@ -129,16 +159,25 @@ class MIDIPlayer {
129
159
  }
130
160
  startTimer() {
131
161
  const endTime = this.midy.totalTime;
132
- this.timer = setInterval(() => {
162
+ this.stopTimer();
163
+ const update = () => {
133
164
  const now = this.midy.currentTime();
134
- const seconds = Math.ceil(now);
135
165
  if (this.currTimeNode) {
166
+ const seconds = Math.ceil(now);
136
167
  this.currTimeNode.textContent = this.formatTime(seconds);
137
168
  }
138
169
  if (this.seekBarNode) {
139
170
  this.seekBarNode.value = now / endTime;
140
171
  }
141
- }, this.currTimeInterval);
172
+ this.timer = requestAnimationFrame(update);
173
+ };
174
+ this.timer = requestAnimationFrame(update);
175
+ }
176
+ stopTimer() {
177
+ if (this.timer) {
178
+ cancelAnimationFrame(this.timer);
179
+ this.timer = null;
180
+ }
142
181
  }
143
182
  async loadMIDI(file) {
144
183
  await this.midy.loadMIDI(file);
@@ -153,27 +192,25 @@ class MIDIPlayer {
153
192
  const paths = [];
154
193
  const { midy, soundFontURL } = this;
155
194
  for (const instrument of midy.instruments) {
156
- const [bankNumber, programNumber] = instrument.split(":").map(Number);
157
- const table = midy.soundFontTable[programNumber];
158
- if (table.has(bankNumber))
195
+ const [bank, program] = instrument.split(":");
196
+ const bankNumber = Number(bank);
197
+ const programNumber = Number(program);
198
+ const index = midy.soundFontTable[programNumber][bankNumber];
199
+ if (index !== undefined)
159
200
  continue;
160
- const program = programNumber.toString().padStart(3, "0");
161
- const path = bankNumber === 128
162
- ? `${soundFontURL}/128.sf3`
163
- : `${soundFontURL}/${program}.sf3`;
164
- paths.push(path);
201
+ const baseName = bankNumber === 128 ? "128" : program;
202
+ paths.push(`${soundFontURL}/${baseName}.sf3`);
165
203
  }
166
204
  return paths;
167
205
  }
168
206
  async start() {
207
+ this.isPlaying = true;
169
208
  const midy = this.midy;
170
- if (midy.soundFonts.length === 0) {
171
- const paths = this.getSoundFontPaths();
172
- await midy.loadSoundFont(paths);
173
- }
209
+ await midy.loadSoundFont(this.getSoundFontPaths());
174
210
  this.startTimer();
175
211
  await midy.start();
176
- clearInterval(this.timer);
212
+ this.stopTimer();
213
+ this.isPlaying = false;
177
214
  if (!midy.isPaused && this.currTimeNode) {
178
215
  this.currTimeNode.textContent = "0:00";
179
216
  this.seekBarNode.value = 0;
@@ -183,11 +220,13 @@ class MIDIPlayer {
183
220
  const midy = this.midy;
184
221
  if (!midy.isPlaying)
185
222
  return;
186
- clearInterval(this.timer);
223
+ this.isStopping = true;
187
224
  this.playNode.style.display = "initial";
188
225
  this.pauseNode.style.display = "none";
189
226
  this.resumeNode.style.display = "none";
227
+ this.stopTimer();
190
228
  await midy.stop();
229
+ this.isPlaying = false;
191
230
  }
192
231
  stop() {
193
232
  const stop = this.button("start", "midi-player-start", "stop", "initial");
@@ -199,32 +238,39 @@ class MIDIPlayer {
199
238
  const { midy, playNode, pauseNode } = this;
200
239
  if (midy.isPlaying || midy.isPaused)
201
240
  return;
241
+ this.isPlaying = true;
202
242
  playNode.style.display = "none";
203
243
  pauseNode.style.display = "initial";
204
244
  await this.start();
245
+ this.isPlaying = false;
205
246
  if (!midy.isPaused) {
206
247
  pauseNode.style.display = "none";
207
248
  playNode.style.display = "initial";
208
249
  }
209
250
  }
210
- handlePause() {
251
+ async handlePause() {
211
252
  const midy = this.midy;
212
253
  if (!midy.isPlaying || midy.isPaused)
213
254
  return;
255
+ this.isPausing = true;
214
256
  this.pauseNode.style.display = "none";
215
257
  this.resumeNode.style.display = "initial";
216
- clearInterval(this.timer);
217
- midy.pause();
258
+ this.stopTimer();
259
+ await midy.pause();
260
+ this.isPausing = false;
261
+ this.isPaused = true;
218
262
  }
219
263
  async handleResume() {
220
264
  const { midy, playNode, pauseNode, resumeNode } = this;
221
265
  if (!midy.isPaused)
222
266
  return;
267
+ this.isPlaying = true;
223
268
  pauseNode.style.display = "initial";
224
269
  resumeNode.style.display = "none";
225
270
  this.startTimer();
226
271
  await midy.resume();
227
- clearInterval(this.timer);
272
+ this.stopTimer();
273
+ this.isPlaying = false;
228
274
  if (!midy.isPaused) {
229
275
  pauseNode.style.display = "none";
230
276
  playNode.style.display = "initial";
@@ -285,11 +331,13 @@ class MIDIPlayer {
285
331
  seekBar() {
286
332
  const seekBar = this.formRange("playback position", "midi-player-seekBar", 0, "initial");
287
333
  seekBar.oninput = (event) => {
334
+ this.isSeeking = true;
288
335
  const time = event.target.value * this.midy.totalTime;
289
336
  this.midy.seekTo(time);
290
337
  if (this.currTimeNode) {
291
338
  this.currTimeNode.textContent = this.formatTime(time);
292
339
  }
340
+ this.isSeeking = false;
293
341
  };
294
342
  this.seekBarNode = seekBar;
295
343
  return seekBar;