action-engine-js 1.0.0

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 (93) hide show
  1. package/LICENSE +45 -0
  2. package/README.md +348 -0
  3. package/actionengine/3rdparty/goblin/goblin.js +9609 -0
  4. package/actionengine/3rdparty/goblin/goblin.min.js +5 -0
  5. package/actionengine/camera/actioncamera.js +90 -0
  6. package/actionengine/camera/cameracollisionhandler.js +69 -0
  7. package/actionengine/character/actioncharacter.js +360 -0
  8. package/actionengine/character/actioncharacter3D.js +61 -0
  9. package/actionengine/core/app.js +430 -0
  10. package/actionengine/debug/basedebugpanel.js +858 -0
  11. package/actionengine/display/canvasmanager.js +75 -0
  12. package/actionengine/display/gl/programmanager.js +570 -0
  13. package/actionengine/display/gl/shaders/lineshader.js +118 -0
  14. package/actionengine/display/gl/shaders/objectshader.js +1756 -0
  15. package/actionengine/display/gl/shaders/particleshader.js +43 -0
  16. package/actionengine/display/gl/shaders/shadowshader.js +319 -0
  17. package/actionengine/display/gl/shaders/spriteshader.js +100 -0
  18. package/actionengine/display/gl/shaders/watershader.js +67 -0
  19. package/actionengine/display/graphics/actionmodel3D.js +191 -0
  20. package/actionengine/display/graphics/actionsprite3D.js +230 -0
  21. package/actionengine/display/graphics/lighting/actiondirectionalshadowlight.js +864 -0
  22. package/actionengine/display/graphics/lighting/actionlight.js +211 -0
  23. package/actionengine/display/graphics/lighting/actionomnidirectionalshadowlight.js +862 -0
  24. package/actionengine/display/graphics/lighting/lightingconstants.js +263 -0
  25. package/actionengine/display/graphics/lighting/lightmanager.js +789 -0
  26. package/actionengine/display/graphics/renderableobject.js +44 -0
  27. package/actionengine/display/graphics/renderers/actionrenderer2D.js +341 -0
  28. package/actionengine/display/graphics/renderers/actionrenderer3D/actionrenderer3D.js +655 -0
  29. package/actionengine/display/graphics/renderers/actionrenderer3D/canvasmanager3D.js +82 -0
  30. package/actionengine/display/graphics/renderers/actionrenderer3D/debugrenderer3D.js +493 -0
  31. package/actionengine/display/graphics/renderers/actionrenderer3D/objectrenderer3D.js +790 -0
  32. package/actionengine/display/graphics/renderers/actionrenderer3D/spriteRenderer3D.js +266 -0
  33. package/actionengine/display/graphics/renderers/actionrenderer3D/sunrenderer3D.js +140 -0
  34. package/actionengine/display/graphics/renderers/actionrenderer3D/waterrenderer3D.js +173 -0
  35. package/actionengine/display/graphics/renderers/actionrenderer3D/weatherrenderer3D.js +87 -0
  36. package/actionengine/display/graphics/texture/proceduraltexture.js +192 -0
  37. package/actionengine/display/graphics/texture/texturemanager.js +242 -0
  38. package/actionengine/display/graphics/texture/textureregistry.js +177 -0
  39. package/actionengine/input/actionscrollablearea.js +1405 -0
  40. package/actionengine/input/inputhandler.js +1647 -0
  41. package/actionengine/math/geometry/geometrybuilder.js +161 -0
  42. package/actionengine/math/geometry/glbexporter.js +364 -0
  43. package/actionengine/math/geometry/glbloader.js +722 -0
  44. package/actionengine/math/geometry/modelcodegenerator.js +97 -0
  45. package/actionengine/math/geometry/triangle.js +33 -0
  46. package/actionengine/math/geometry/triangleutils.js +34 -0
  47. package/actionengine/math/mathutils.js +25 -0
  48. package/actionengine/math/matrix4.js +785 -0
  49. package/actionengine/math/physics/actionphysics.js +108 -0
  50. package/actionengine/math/physics/actionphysicsobject3D.js +164 -0
  51. package/actionengine/math/physics/actionphysicsworld3D.js +238 -0
  52. package/actionengine/math/physics/actionraycast.js +129 -0
  53. package/actionengine/math/physics/shapes/actionphysicsbox3D.js +158 -0
  54. package/actionengine/math/physics/shapes/actionphysicscapsule3D.js +200 -0
  55. package/actionengine/math/physics/shapes/actionphysicscompoundshape3D.js +147 -0
  56. package/actionengine/math/physics/shapes/actionphysicscone3D.js +126 -0
  57. package/actionengine/math/physics/shapes/actionphysicsconvexshape3D.js +72 -0
  58. package/actionengine/math/physics/shapes/actionphysicscylinder3D.js +117 -0
  59. package/actionengine/math/physics/shapes/actionphysicsmesh3D.js +74 -0
  60. package/actionengine/math/physics/shapes/actionphysicsplane3D.js +100 -0
  61. package/actionengine/math/physics/shapes/actionphysicssphere3D.js +95 -0
  62. package/actionengine/math/quaternion.js +61 -0
  63. package/actionengine/math/vector2.js +277 -0
  64. package/actionengine/math/vector3.js +318 -0
  65. package/actionengine/math/viewfrustum.js +136 -0
  66. package/actionengine/network/ACTIONNETREADME.md +810 -0
  67. package/actionengine/network/client/ActionNetManager.js +802 -0
  68. package/actionengine/network/client/ActionNetManagerGUI.js +1709 -0
  69. package/actionengine/network/client/ActionNetManagerP2P.js +1537 -0
  70. package/actionengine/network/client/SyncSystem.js +422 -0
  71. package/actionengine/network/p2p/ActionNetPeer.js +142 -0
  72. package/actionengine/network/p2p/ActionNetTrackerClient.js +623 -0
  73. package/actionengine/network/p2p/DataConnection.js +282 -0
  74. package/actionengine/network/p2p/README.md +510 -0
  75. package/actionengine/network/p2p/example.html +502 -0
  76. package/actionengine/network/server/ActionNetServer.js +577 -0
  77. package/actionengine/network/server/ActionNetServerSSL.js +579 -0
  78. package/actionengine/network/server/ActionNetServerUtils.js +458 -0
  79. package/actionengine/network/server/SERVERREADME.md +314 -0
  80. package/actionengine/network/server/package-lock.json +35 -0
  81. package/actionengine/network/server/package.json +13 -0
  82. package/actionengine/network/server/start.bat +27 -0
  83. package/actionengine/network/server/start.sh +25 -0
  84. package/actionengine/network/server/startwss.bat +27 -0
  85. package/actionengine/sound/audiomanager.js +1589 -0
  86. package/actionengine/sound/soundfont/ACTIONSOUNDFONT_README.md +205 -0
  87. package/actionengine/sound/soundfont/actionparser.js +718 -0
  88. package/actionengine/sound/soundfont/actionreverb.js +252 -0
  89. package/actionengine/sound/soundfont/actionsoundfont.js +543 -0
  90. package/actionengine/sound/soundfont/sf2playerlicence.txt +29 -0
  91. package/actionengine/sound/soundfont/soundfont.js +2 -0
  92. package/dist/action-engine.min.js +328 -0
  93. package/package.json +35 -0
@@ -0,0 +1,718 @@
1
+ // actionengine/sound/actionparser.js
2
+ // ActionParser - SoundFont2 file parser
3
+
4
+ /**
5
+ * RIFF Chunk Class
6
+ */
7
+ class ActionRiffChunk {
8
+ constructor(type, size, offset) {
9
+ this.type = type;
10
+ this.size = size;
11
+ this.offset = offset;
12
+ }
13
+ }
14
+
15
+ /**
16
+ * RIFF Parser Class
17
+ */
18
+ class ActionRiff {
19
+ constructor(input, optParams = {}) {
20
+ this.input = input;
21
+ this.ip = optParams.index || 0;
22
+ this.length = optParams.length || input.length - this.ip;
23
+ this.chunkList = [];
24
+ this.offset = this.ip;
25
+ this.padding = optParams.padding !== undefined ? optParams.padding : true;
26
+ this.bigEndian = optParams.bigEndian !== undefined ? optParams.bigEndian : false;
27
+ }
28
+
29
+ parse() {
30
+ const end = this.length + this.offset;
31
+ this.chunkList = [];
32
+
33
+ while (this.ip < end) {
34
+ this.parseChunk();
35
+ }
36
+ }
37
+
38
+ parseChunk() {
39
+ const data = this.input;
40
+ let ip = this.ip;
41
+
42
+ // Read chunk type (4 chars)
43
+ const type = String.fromCharCode(
44
+ data[ip++], data[ip++], data[ip++], data[ip++]
45
+ );
46
+
47
+ // Read chunk size (4 bytes)
48
+ const size = this.bigEndian ?
49
+ ((data[ip++] << 24) | (data[ip++] << 16) | (data[ip++] << 8) | data[ip++]) >>> 0 :
50
+ ((data[ip++]) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0;
51
+
52
+ this.chunkList.push(new ActionRiffChunk(type, size, ip));
53
+
54
+ ip += size;
55
+
56
+ // Apply padding if needed
57
+ if (this.padding && ((ip - this.offset) & 1) === 1) {
58
+ ip++;
59
+ }
60
+
61
+ this.ip = ip;
62
+ }
63
+
64
+ getChunk(index) {
65
+ return this.chunkList[index] || null;
66
+ }
67
+
68
+ getNumberOfChunks() {
69
+ return this.chunkList.length;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * ActionParser Class
75
+ * Parses SoundFont2 files
76
+ */
77
+ class ActionParser {
78
+ constructor(input, optParams = {}) {
79
+ this.input = input;
80
+ this.parserOption = optParams.parserOption || {};
81
+ this.sampleRate = optParams.sampleRate || 22050;
82
+
83
+ // SF2 data structures
84
+ this.presetHeader = [];
85
+ this.presetZone = [];
86
+ this.presetZoneModulator = [];
87
+ this.presetZoneGenerator = [];
88
+ this.instrument = [];
89
+ this.instrumentZone = [];
90
+ this.instrumentZoneModulator = [];
91
+ this.instrumentZoneGenerator = [];
92
+ this.sampleHeader = [];
93
+ this.sample = [];
94
+ this.samplingData = null;
95
+
96
+ // Generator enumerator table
97
+ this.GeneratorEnumeratorTable = [
98
+ 'startAddrsOffset',
99
+ 'endAddrsOffset',
100
+ 'startloopAddrsOffset',
101
+ 'endloopAddrsOffset',
102
+ 'startAddrsCoarseOffset',
103
+ 'modLfoToPitch',
104
+ 'vibLfoToPitch',
105
+ 'modEnvToPitch',
106
+ 'initialFilterFc',
107
+ 'initialFilterQ',
108
+ 'modLfoToFilterFc',
109
+ 'modEnvToFilterFc',
110
+ 'endAddrsCoarseOffset',
111
+ 'modLfoToVolume',
112
+ undefined, // 14
113
+ 'chorusEffectsSend',
114
+ 'reverbEffectsSend',
115
+ 'pan',
116
+ undefined, undefined, undefined, // 18, 19, 20
117
+ 'delayModLFO',
118
+ 'freqModLFO',
119
+ 'delayVibLFO',
120
+ 'freqVibLFO',
121
+ 'delayModEnv',
122
+ 'attackModEnv',
123
+ 'holdModEnv',
124
+ 'decayModEnv',
125
+ 'sustainModEnv',
126
+ 'releaseModEnv',
127
+ 'keynumToModEnvHold',
128
+ 'keynumToModEnvDecay',
129
+ 'delayVolEnv',
130
+ 'attackVolEnv',
131
+ 'holdVolEnv',
132
+ 'decayVolEnv',
133
+ 'sustainVolEnv',
134
+ 'releaseVolEnv',
135
+ 'keynumToVolEnvHold',
136
+ 'keynumToVolEnvDecay',
137
+ 'instrument',
138
+ undefined, // 42
139
+ 'keyRange',
140
+ 'velRange',
141
+ 'startloopAddrsCoarseOffset',
142
+ 'keynum',
143
+ 'velocity',
144
+ 'initialAttenuation',
145
+ undefined, // 49
146
+ 'endloopAddrsCoarseOffset',
147
+ 'coarseTune',
148
+ 'fineTune',
149
+ 'sampleID',
150
+ 'sampleModes',
151
+ undefined, // 55
152
+ 'scaleTuning',
153
+ 'exclusiveClass',
154
+ 'overridingRootKey',
155
+ 'endOper'
156
+ ];
157
+ }
158
+
159
+ parse() {
160
+ const parser = new ActionRiff(this.input, this.parserOption);
161
+ parser.parse();
162
+
163
+ if (parser.chunkList.length !== 1) {
164
+ throw new Error('Wrong chunk length');
165
+ }
166
+
167
+ const chunk = parser.getChunk(0);
168
+ if (!chunk) {
169
+ throw new Error('Chunk not found');
170
+ }
171
+
172
+ this.parseRiffChunk(chunk);
173
+ this.input = null;
174
+ }
175
+
176
+ parseRiffChunk(chunk) {
177
+ const data = this.input;
178
+ let ip = chunk.offset;
179
+
180
+ if (chunk.type !== 'RIFF') {
181
+ throw new Error('Invalid chunk type: ' + chunk.type);
182
+ }
183
+
184
+ // Check signature
185
+ const signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]);
186
+ if (signature !== 'sfbk') {
187
+ throw new Error('Invalid signature: ' + signature);
188
+ }
189
+
190
+ const parser = new ActionRiff(data, { index: ip, length: chunk.size - 4 });
191
+ parser.parse();
192
+
193
+ if (parser.getNumberOfChunks() !== 3) {
194
+ throw new Error('Invalid sfbk structure');
195
+ }
196
+
197
+ // Parse the three main lists
198
+ this.parseInfoList(parser.getChunk(0));
199
+ this.parseSdtaList(parser.getChunk(1));
200
+ this.parsePdtaList(parser.getChunk(2));
201
+ }
202
+
203
+ parseInfoList(chunk) {
204
+ const data = this.input;
205
+ let ip = chunk.offset;
206
+
207
+ if (chunk.type !== 'LIST') {
208
+ throw new Error('Invalid chunk type: ' + chunk.type);
209
+ }
210
+
211
+ const signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]);
212
+ if (signature !== 'INFO') {
213
+ throw new Error('Invalid signature: ' + signature);
214
+ }
215
+
216
+ // INFO list parsed (contains metadata we don't currently need)
217
+ const parser = new ActionRiff(data, { index: ip, length: chunk.size - 4 });
218
+ parser.parse();
219
+ }
220
+
221
+ parseSdtaList(chunk) {
222
+ const data = this.input;
223
+ let ip = chunk.offset;
224
+
225
+ if (chunk.type !== 'LIST') {
226
+ throw new Error('Invalid chunk type: ' + chunk.type);
227
+ }
228
+
229
+ const signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]);
230
+ if (signature !== 'sdta') {
231
+ throw new Error('Invalid signature: ' + signature);
232
+ }
233
+
234
+ const parser = new ActionRiff(data, { index: ip, length: chunk.size - 4 });
235
+ parser.parse();
236
+
237
+ if (parser.chunkList.length !== 1) {
238
+ throw new Error('Invalid sdta structure');
239
+ }
240
+
241
+ this.samplingData = parser.getChunk(0);
242
+ }
243
+
244
+ parsePdtaList(chunk) {
245
+ const data = this.input;
246
+ let ip = chunk.offset;
247
+
248
+ if (chunk.type !== 'LIST') {
249
+ throw new Error('Invalid chunk type: ' + chunk.type);
250
+ }
251
+
252
+ const signature = String.fromCharCode(data[ip++], data[ip++], data[ip++], data[ip++]);
253
+ if (signature !== 'pdta') {
254
+ throw new Error('Invalid signature: ' + signature);
255
+ }
256
+
257
+ const parser = new ActionRiff(data, { index: ip, length: chunk.size - 4 });
258
+ parser.parse();
259
+
260
+ if (parser.getNumberOfChunks() !== 9) {
261
+ throw new Error('Invalid pdta chunk');
262
+ }
263
+
264
+ // Parse all preset data chunks
265
+ this.parsePhdr(parser.getChunk(0));
266
+ this.parsePbag(parser.getChunk(1));
267
+ this.parsePmod(parser.getChunk(2));
268
+ this.parsePgen(parser.getChunk(3));
269
+ this.parseInst(parser.getChunk(4));
270
+ this.parseIbag(parser.getChunk(5));
271
+ this.parseImod(parser.getChunk(6));
272
+ this.parseIgen(parser.getChunk(7));
273
+ this.parseShdr(parser.getChunk(8));
274
+ }
275
+
276
+ parsePhdr(chunk) {
277
+ const data = this.input;
278
+ let ip = chunk.offset;
279
+ const size = chunk.offset + chunk.size;
280
+
281
+ if (chunk.type !== 'phdr') {
282
+ throw new Error('Invalid chunk type: ' + chunk.type);
283
+ }
284
+
285
+ this.presetHeader = [];
286
+
287
+ while (ip < size) {
288
+ this.presetHeader.push({
289
+ presetName: String.fromCharCode.apply(null, data.subarray(ip, ip += 20)),
290
+ preset: data[ip++] | (data[ip++] << 8),
291
+ bank: data[ip++] | (data[ip++] << 8),
292
+ presetBagIndex: data[ip++] | (data[ip++] << 8),
293
+ library: (data[ip++] | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0,
294
+ genre: (data[ip++] | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0,
295
+ morphology: (data[ip++] | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0
296
+ });
297
+ }
298
+ }
299
+
300
+ parsePbag(chunk) {
301
+ const data = this.input;
302
+ let ip = chunk.offset;
303
+ const size = chunk.offset + chunk.size;
304
+
305
+ if (chunk.type !== 'pbag') {
306
+ throw new Error('Invalid chunk type: ' + chunk.type);
307
+ }
308
+
309
+ this.presetZone = [];
310
+
311
+ while (ip < size) {
312
+ this.presetZone.push({
313
+ presetGeneratorIndex: data[ip++] | (data[ip++] << 8),
314
+ presetModulatorIndex: data[ip++] | (data[ip++] << 8)
315
+ });
316
+ }
317
+ }
318
+
319
+ parsePmod(chunk) {
320
+ if (chunk.type !== 'pmod') {
321
+ throw new Error('Invalid chunk type: ' + chunk.type);
322
+ }
323
+ this.presetZoneModulator = this.parseModulator(chunk);
324
+ }
325
+
326
+ parsePgen(chunk) {
327
+ if (chunk.type !== 'pgen') {
328
+ throw new Error('Invalid chunk type: ' + chunk.type);
329
+ }
330
+ this.presetZoneGenerator = this.parseGenerator(chunk);
331
+ }
332
+
333
+ parseInst(chunk) {
334
+ const data = this.input;
335
+ let ip = chunk.offset;
336
+ const size = chunk.offset + chunk.size;
337
+
338
+ if (chunk.type !== 'inst') {
339
+ throw new Error('Invalid chunk type: ' + chunk.type);
340
+ }
341
+
342
+ this.instrument = [];
343
+
344
+ while (ip < size) {
345
+ this.instrument.push({
346
+ instrumentName: String.fromCharCode.apply(null, data.subarray(ip, ip += 20)),
347
+ instrumentBagIndex: data[ip++] | (data[ip++] << 8)
348
+ });
349
+ }
350
+ }
351
+
352
+ parseIbag(chunk) {
353
+ const data = this.input;
354
+ let ip = chunk.offset;
355
+ const size = chunk.offset + chunk.size;
356
+
357
+ if (chunk.type !== 'ibag') {
358
+ throw new Error('Invalid chunk type: ' + chunk.type);
359
+ }
360
+
361
+ this.instrumentZone = [];
362
+
363
+ while (ip < size) {
364
+ this.instrumentZone.push({
365
+ instrumentGeneratorIndex: data[ip++] | (data[ip++] << 8),
366
+ instrumentModulatorIndex: data[ip++] | (data[ip++] << 8)
367
+ });
368
+ }
369
+ }
370
+
371
+ parseImod(chunk) {
372
+ if (chunk.type !== 'imod') {
373
+ throw new Error('Invalid chunk type: ' + chunk.type);
374
+ }
375
+ this.instrumentZoneModulator = this.parseModulator(chunk);
376
+ }
377
+
378
+ parseIgen(chunk) {
379
+ if (chunk.type !== 'igen') {
380
+ throw new Error('Invalid chunk type: ' + chunk.type);
381
+ }
382
+ this.instrumentZoneGenerator = this.parseGenerator(chunk);
383
+ }
384
+
385
+ parseShdr(chunk) {
386
+ const data = this.input;
387
+ let ip = chunk.offset;
388
+ const size = chunk.offset + chunk.size;
389
+
390
+ if (chunk.type !== 'shdr') {
391
+ throw new Error('Invalid chunk type: ' + chunk.type);
392
+ }
393
+
394
+ this.sample = [];
395
+ this.sampleHeader = [];
396
+
397
+ while (ip < size) {
398
+ const sampleName = String.fromCharCode.apply(null, data.subarray(ip, ip += 20));
399
+ let start = ((data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0;
400
+ let end = ((data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0;
401
+ let startLoop = ((data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0;
402
+ let endLoop = ((data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0;
403
+ let sampleRate = ((data[ip++] << 0) | (data[ip++] << 8) | (data[ip++] << 16) | (data[ip++] << 24)) >>> 0;
404
+ const originalPitch = data[ip++];
405
+ const pitchCorrection = (data[ip++] << 24) >> 24;
406
+ const sampleLink = data[ip++] | (data[ip++] << 8);
407
+ const sampleType = data[ip++] | (data[ip++] << 8);
408
+
409
+ // Extract sample data
410
+ let sample = new Int16Array(new Uint8Array(data.subarray(
411
+ this.samplingData.offset + start * 2,
412
+ this.samplingData.offset + end * 2
413
+ )).buffer);
414
+
415
+ startLoop -= start;
416
+ endLoop -= start;
417
+
418
+ // Adjust sample rate if needed
419
+ if (sampleRate > 0) {
420
+ const adjust = this.adjustSampleData(sample, sampleRate);
421
+ sample = adjust.sample;
422
+ sampleRate *= adjust.multiply;
423
+ startLoop *= adjust.multiply;
424
+ endLoop *= adjust.multiply;
425
+ }
426
+
427
+ this.sample.push(sample);
428
+ this.sampleHeader.push({
429
+ sampleName,
430
+ start,
431
+ end,
432
+ startLoop,
433
+ endLoop,
434
+ sampleRate,
435
+ originalPitch,
436
+ pitchCorrection,
437
+ sampleLink,
438
+ sampleType
439
+ });
440
+ }
441
+ }
442
+
443
+ adjustSampleData(sample, sampleRate) {
444
+ let newSample;
445
+ let multiply = 1;
446
+
447
+ // Upsample if sample rate is too low
448
+ while (sampleRate < this.sampleRate) {
449
+ newSample = new Int16Array(sample.length * 2);
450
+ let j = 0;
451
+ for (let i = 0; i < sample.length; i++) {
452
+ newSample[j++] = sample[i];
453
+ newSample[j++] = sample[i];
454
+ }
455
+ sample = newSample;
456
+ multiply *= 2;
457
+ sampleRate *= 2;
458
+ }
459
+
460
+ return { sample, multiply };
461
+ }
462
+
463
+ parseModulator(chunk) {
464
+ const data = this.input;
465
+ let ip = chunk.offset;
466
+ const size = chunk.offset + chunk.size;
467
+ const output = [];
468
+
469
+ while (ip < size) {
470
+ ip += 2; // Src Oper
471
+
472
+ const code = data[ip++] | (data[ip++] << 8);
473
+ const key = this.GeneratorEnumeratorTable[code];
474
+
475
+ if (key === undefined) {
476
+ output.push({
477
+ type: key,
478
+ value: {
479
+ code,
480
+ amount: (data[ip] | (data[ip + 1] << 8)) << 16 >> 16,
481
+ lo: data[ip++],
482
+ hi: data[ip++]
483
+ }
484
+ });
485
+ } else {
486
+ switch (key) {
487
+ case 'keyRange':
488
+ case 'velRange':
489
+ case 'keynum':
490
+ case 'velocity':
491
+ output.push({
492
+ type: key,
493
+ value: {
494
+ lo: data[ip++],
495
+ hi: data[ip++]
496
+ }
497
+ });
498
+ break;
499
+ default:
500
+ output.push({
501
+ type: key,
502
+ value: {
503
+ amount: (data[ip++] | (data[ip++] << 8)) << 16 >> 16
504
+ }
505
+ });
506
+ break;
507
+ }
508
+ }
509
+
510
+ ip += 2; // AmtSrcOper
511
+ ip += 2; // Trans Oper
512
+ }
513
+
514
+ return output;
515
+ }
516
+
517
+ parseGenerator(chunk) {
518
+ const data = this.input;
519
+ let ip = chunk.offset;
520
+ const size = chunk.offset + chunk.size;
521
+ const output = [];
522
+
523
+ while (ip < size) {
524
+ const code = data[ip++] | (data[ip++] << 8);
525
+ const key = this.GeneratorEnumeratorTable[code];
526
+
527
+ if (key === undefined) {
528
+ output.push({
529
+ type: key,
530
+ value: {
531
+ code,
532
+ amount: (data[ip] | (data[ip + 1] << 8)) << 16 >> 16,
533
+ lo: data[ip++],
534
+ hi: data[ip++]
535
+ }
536
+ });
537
+ continue;
538
+ }
539
+
540
+ switch (key) {
541
+ case 'keynum':
542
+ case 'keyRange':
543
+ case 'velRange':
544
+ case 'velocity':
545
+ output.push({
546
+ type: key,
547
+ value: {
548
+ lo: data[ip++],
549
+ hi: data[ip++]
550
+ }
551
+ });
552
+ break;
553
+ default:
554
+ output.push({
555
+ type: key,
556
+ value: {
557
+ amount: (data[ip++] | (data[ip++] << 8)) << 16 >> 16
558
+ }
559
+ });
560
+ break;
561
+ }
562
+ }
563
+
564
+ return output;
565
+ }
566
+
567
+ createInstrument() {
568
+ const output = [];
569
+
570
+ for (let i = 0; i < this.instrument.length; i++) {
571
+ const bagIndex = this.instrument[i].instrumentBagIndex;
572
+ const bagIndexEnd = this.instrument[i + 1] ? this.instrument[i + 1].instrumentBagIndex : this.instrumentZone.length;
573
+ const zoneInfo = [];
574
+
575
+ for (let j = bagIndex; j < bagIndexEnd; j++) {
576
+ const instrumentGenerator = this.createInstrumentGenerator(this.instrumentZone, j);
577
+ const instrumentModulator = this.createInstrumentModulator(this.instrumentZone, j);
578
+
579
+ zoneInfo.push({
580
+ generator: instrumentGenerator.generator,
581
+ generatorSequence: instrumentGenerator.generatorInfo,
582
+ modulator: instrumentModulator.modulator,
583
+ modulatorSequence: instrumentModulator.modulatorInfo
584
+ });
585
+ }
586
+
587
+ output.push({
588
+ name: this.instrument[i].instrumentName,
589
+ info: zoneInfo
590
+ });
591
+ }
592
+
593
+ return output;
594
+ }
595
+
596
+ createPreset() {
597
+ const output = [];
598
+
599
+ for (let i = 0; i < this.presetHeader.length; i++) {
600
+ const bagIndex = this.presetHeader[i].presetBagIndex;
601
+ const bagIndexEnd = this.presetHeader[i + 1] ? this.presetHeader[i + 1].presetBagIndex : this.presetZone.length;
602
+ const zoneInfo = [];
603
+ let instrument = null;
604
+
605
+ for (let j = bagIndex; j < bagIndexEnd; j++) {
606
+ const presetGenerator = this.createPresetGenerator(this.presetZone, j);
607
+ const presetModulator = this.createPresetModulator(this.presetZone, j);
608
+
609
+ zoneInfo.push({
610
+ generator: presetGenerator.generator,
611
+ generatorSequence: presetGenerator.generatorInfo,
612
+ modulator: presetModulator.modulator,
613
+ modulatorSequence: presetModulator.modulatorInfo
614
+ });
615
+
616
+ instrument = presetGenerator.generator.instrument !== undefined ?
617
+ presetGenerator.generator.instrument.amount :
618
+ presetModulator.modulator.instrument !== undefined ?
619
+ presetModulator.modulator.instrument.amount :
620
+ null;
621
+ }
622
+
623
+ output.push({
624
+ name: this.presetHeader[i].presetName,
625
+ info: zoneInfo,
626
+ header: this.presetHeader[i],
627
+ instrument
628
+ });
629
+ }
630
+
631
+ return output;
632
+ }
633
+
634
+ createInstrumentGenerator(zone, index) {
635
+ const modgen = this.createBagModGen(
636
+ zone,
637
+ zone[index].instrumentGeneratorIndex,
638
+ zone[index + 1] ? zone[index + 1].instrumentGeneratorIndex : this.instrumentZoneGenerator.length,
639
+ this.instrumentZoneGenerator
640
+ );
641
+
642
+ return {
643
+ generator: modgen.modgen,
644
+ generatorInfo: modgen.modgenInfo
645
+ };
646
+ }
647
+
648
+ createInstrumentModulator(zone, index) {
649
+ const modgen = this.createBagModGen(
650
+ zone,
651
+ zone[index].instrumentModulatorIndex,
652
+ zone[index + 1] ? zone[index + 1].instrumentModulatorIndex : this.instrumentZoneModulator.length,
653
+ this.instrumentZoneModulator
654
+ );
655
+
656
+ return {
657
+ modulator: modgen.modgen,
658
+ modulatorInfo: modgen.modgenInfo
659
+ };
660
+ }
661
+
662
+ createPresetGenerator(zone, index) {
663
+ const modgen = this.createBagModGen(
664
+ zone,
665
+ zone[index].presetGeneratorIndex,
666
+ zone[index + 1] ? zone[index + 1].presetGeneratorIndex : this.presetZoneGenerator.length,
667
+ this.presetZoneGenerator
668
+ );
669
+
670
+ return {
671
+ generator: modgen.modgen,
672
+ generatorInfo: modgen.modgenInfo
673
+ };
674
+ }
675
+
676
+ createPresetModulator(zone, index) {
677
+ const modgen = this.createBagModGen(
678
+ zone,
679
+ zone[index].presetModulatorIndex,
680
+ zone[index + 1] ? zone[index + 1].presetModulatorIndex : this.presetZoneModulator.length,
681
+ this.presetZoneModulator
682
+ );
683
+
684
+ return {
685
+ modulator: modgen.modgen,
686
+ modulatorInfo: modgen.modgenInfo
687
+ };
688
+ }
689
+
690
+ createBagModGen(zone, indexStart, indexEnd, zoneModGen) {
691
+ const modgenInfo = [];
692
+ const modgen = {
693
+ unknown: [],
694
+ keyRange: {
695
+ hi: 127,
696
+ lo: 0
697
+ }
698
+ };
699
+
700
+ for (let i = indexStart; i < indexEnd; i++) {
701
+ const info = zoneModGen[i];
702
+ modgenInfo.push(info);
703
+
704
+ if (info.type === 'unknown') {
705
+ modgen.unknown.push(info.value);
706
+ } else {
707
+ modgen[info.type] = info.value;
708
+ }
709
+ }
710
+
711
+ return {
712
+ modgen,
713
+ modgenInfo
714
+ };
715
+ }
716
+ }
717
+
718
+ window.ActionParser = ActionParser;