Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/media/sound/DLSSoundbank.java
38924 views
1
/*
2
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
package com.sun.media.sound;
26
27
import java.io.File;
28
import java.io.FileInputStream;
29
import java.io.IOException;
30
import java.io.InputStream;
31
import java.io.OutputStream;
32
import java.net.URL;
33
import java.util.ArrayList;
34
import java.util.Arrays;
35
import java.util.HashMap;
36
import java.util.List;
37
import java.util.Map;
38
import java.util.Stack;
39
40
import javax.sound.midi.Instrument;
41
import javax.sound.midi.Patch;
42
import javax.sound.midi.Soundbank;
43
import javax.sound.midi.SoundbankResource;
44
import javax.sound.sampled.AudioFormat;
45
import javax.sound.sampled.AudioInputStream;
46
import javax.sound.sampled.AudioSystem;
47
import javax.sound.sampled.AudioFormat.Encoding;
48
49
/**
50
* A DLS Level 1 and Level 2 soundbank reader (from files/url/streams).
51
*
52
* @author Karl Helgason
53
*/
54
public final class DLSSoundbank implements Soundbank {
55
56
static private class DLSID {
57
long i1;
58
int s1;
59
int s2;
60
int x1;
61
int x2;
62
int x3;
63
int x4;
64
int x5;
65
int x6;
66
int x7;
67
int x8;
68
69
private DLSID() {
70
}
71
72
DLSID(long i1, int s1, int s2, int x1, int x2, int x3, int x4,
73
int x5, int x6, int x7, int x8) {
74
this.i1 = i1;
75
this.s1 = s1;
76
this.s2 = s2;
77
this.x1 = x1;
78
this.x2 = x2;
79
this.x3 = x3;
80
this.x4 = x4;
81
this.x5 = x5;
82
this.x6 = x6;
83
this.x7 = x7;
84
this.x8 = x8;
85
}
86
87
public static DLSID read(RIFFReader riff) throws IOException {
88
DLSID d = new DLSID();
89
d.i1 = riff.readUnsignedInt();
90
d.s1 = riff.readUnsignedShort();
91
d.s2 = riff.readUnsignedShort();
92
d.x1 = riff.readUnsignedByte();
93
d.x2 = riff.readUnsignedByte();
94
d.x3 = riff.readUnsignedByte();
95
d.x4 = riff.readUnsignedByte();
96
d.x5 = riff.readUnsignedByte();
97
d.x6 = riff.readUnsignedByte();
98
d.x7 = riff.readUnsignedByte();
99
d.x8 = riff.readUnsignedByte();
100
return d;
101
}
102
103
public int hashCode() {
104
return (int)i1;
105
}
106
107
public boolean equals(Object obj) {
108
if (!(obj instanceof DLSID)) {
109
return false;
110
}
111
DLSID t = (DLSID) obj;
112
return i1 == t.i1 && s1 == t.s1 && s2 == t.s2
113
&& x1 == t.x1 && x2 == t.x2 && x3 == t.x3 && x4 == t.x4
114
&& x5 == t.x5 && x6 == t.x6 && x7 == t.x7 && x8 == t.x8;
115
}
116
}
117
118
/** X = X & Y */
119
private static final int DLS_CDL_AND = 0x0001;
120
/** X = X | Y */
121
private static final int DLS_CDL_OR = 0x0002;
122
/** X = X ^ Y */
123
private static final int DLS_CDL_XOR = 0x0003;
124
/** X = X + Y */
125
private static final int DLS_CDL_ADD = 0x0004;
126
/** X = X - Y */
127
private static final int DLS_CDL_SUBTRACT = 0x0005;
128
/** X = X * Y */
129
private static final int DLS_CDL_MULTIPLY = 0x0006;
130
/** X = X / Y */
131
private static final int DLS_CDL_DIVIDE = 0x0007;
132
/** X = X && Y */
133
private static final int DLS_CDL_LOGICAL_AND = 0x0008;
134
/** X = X || Y */
135
private static final int DLS_CDL_LOGICAL_OR = 0x0009;
136
/** X = (X < Y) */
137
private static final int DLS_CDL_LT = 0x000A;
138
/** X = (X <= Y) */
139
private static final int DLS_CDL_LE = 0x000B;
140
/** X = (X > Y) */
141
private static final int DLS_CDL_GT = 0x000C;
142
/** X = (X >= Y) */
143
private static final int DLS_CDL_GE = 0x000D;
144
/** X = (X == Y) */
145
private static final int DLS_CDL_EQ = 0x000E;
146
/** X = !X */
147
private static final int DLS_CDL_NOT = 0x000F;
148
/** 32-bit constant */
149
private static final int DLS_CDL_CONST = 0x0010;
150
/** 32-bit value returned from query */
151
private static final int DLS_CDL_QUERY = 0x0011;
152
/** 32-bit value returned from query */
153
private static final int DLS_CDL_QUERYSUPPORTED = 0x0012;
154
155
private static final DLSID DLSID_GMInHardware = new DLSID(0x178f2f24,
156
0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
157
private static final DLSID DLSID_GSInHardware = new DLSID(0x178f2f25,
158
0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
159
private static final DLSID DLSID_XGInHardware = new DLSID(0x178f2f26,
160
0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
161
private static final DLSID DLSID_SupportsDLS1 = new DLSID(0x178f2f27,
162
0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
163
private static final DLSID DLSID_SupportsDLS2 = new DLSID(0xf14599e5,
164
0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
165
private static final DLSID DLSID_SampleMemorySize = new DLSID(0x178f2f28,
166
0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
167
private static final DLSID DLSID_ManufacturersID = new DLSID(0xb03e1181,
168
0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
169
private static final DLSID DLSID_ProductID = new DLSID(0xb03e1182,
170
0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
171
private static final DLSID DLSID_SamplePlaybackRate = new DLSID(0x2a91f713,
172
0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
173
174
private long major = -1;
175
private long minor = -1;
176
177
private final DLSInfo info = new DLSInfo();
178
179
private final List<DLSInstrument> instruments = new ArrayList<DLSInstrument>();
180
private final List<DLSSample> samples = new ArrayList<DLSSample>();
181
182
private boolean largeFormat = false;
183
private File sampleFile;
184
185
public DLSSoundbank() {
186
}
187
188
public DLSSoundbank(URL url) throws IOException {
189
InputStream is = url.openStream();
190
try {
191
readSoundbank(is);
192
} finally {
193
is.close();
194
}
195
}
196
197
public DLSSoundbank(File file) throws IOException {
198
largeFormat = true;
199
sampleFile = file;
200
InputStream is = new FileInputStream(file);
201
try {
202
readSoundbank(is);
203
} finally {
204
is.close();
205
}
206
}
207
208
public DLSSoundbank(InputStream inputstream) throws IOException {
209
readSoundbank(inputstream);
210
}
211
212
private void readSoundbank(InputStream inputstream) throws IOException {
213
RIFFReader riff = new RIFFReader(inputstream);
214
if (!riff.getFormat().equals("RIFF")) {
215
throw new RIFFInvalidFormatException(
216
"Input stream is not a valid RIFF stream!");
217
}
218
if (!riff.getType().equals("DLS ")) {
219
throw new RIFFInvalidFormatException(
220
"Input stream is not a valid DLS soundbank!");
221
}
222
while (riff.hasNextChunk()) {
223
RIFFReader chunk = riff.nextChunk();
224
if (chunk.getFormat().equals("LIST")) {
225
if (chunk.getType().equals("INFO"))
226
readInfoChunk(chunk);
227
if (chunk.getType().equals("lins"))
228
readLinsChunk(chunk);
229
if (chunk.getType().equals("wvpl"))
230
readWvplChunk(chunk);
231
} else {
232
if (chunk.getFormat().equals("cdl ")) {
233
if (!readCdlChunk(chunk)) {
234
throw new RIFFInvalidFormatException(
235
"DLS file isn't supported!");
236
}
237
}
238
if (chunk.getFormat().equals("colh")) {
239
// skipped because we will load the entire bank into memory
240
// long instrumentcount = chunk.readUnsignedInt();
241
// System.out.println("instrumentcount = "+ instrumentcount);
242
}
243
if (chunk.getFormat().equals("ptbl")) {
244
// Pool Table Chunk
245
// skipped because we will load the entire bank into memory
246
}
247
if (chunk.getFormat().equals("vers")) {
248
major = chunk.readUnsignedInt();
249
minor = chunk.readUnsignedInt();
250
}
251
}
252
}
253
254
for (Map.Entry<DLSRegion, Long> entry : temp_rgnassign.entrySet()) {
255
entry.getKey().sample = samples.get((int)entry.getValue().longValue());
256
}
257
258
temp_rgnassign = null;
259
}
260
261
private boolean cdlIsQuerySupported(DLSID uuid) {
262
return uuid.equals(DLSID_GMInHardware)
263
|| uuid.equals(DLSID_GSInHardware)
264
|| uuid.equals(DLSID_XGInHardware)
265
|| uuid.equals(DLSID_SupportsDLS1)
266
|| uuid.equals(DLSID_SupportsDLS2)
267
|| uuid.equals(DLSID_SampleMemorySize)
268
|| uuid.equals(DLSID_ManufacturersID)
269
|| uuid.equals(DLSID_ProductID)
270
|| uuid.equals(DLSID_SamplePlaybackRate);
271
}
272
273
private long cdlQuery(DLSID uuid) {
274
if (uuid.equals(DLSID_GMInHardware))
275
return 1;
276
if (uuid.equals(DLSID_GSInHardware))
277
return 0;
278
if (uuid.equals(DLSID_XGInHardware))
279
return 0;
280
if (uuid.equals(DLSID_SupportsDLS1))
281
return 1;
282
if (uuid.equals(DLSID_SupportsDLS2))
283
return 1;
284
if (uuid.equals(DLSID_SampleMemorySize))
285
return Runtime.getRuntime().totalMemory();
286
if (uuid.equals(DLSID_ManufacturersID))
287
return 0;
288
if (uuid.equals(DLSID_ProductID))
289
return 0;
290
if (uuid.equals(DLSID_SamplePlaybackRate))
291
return 44100;
292
return 0;
293
}
294
295
296
// Reading cdl-ck Chunk
297
// "cdl " chunk can only appear inside : DLS,lart,lar2,rgn,rgn2
298
private boolean readCdlChunk(RIFFReader riff) throws IOException {
299
300
DLSID uuid;
301
long x;
302
long y;
303
Stack<Long> stack = new Stack<Long>();
304
305
while (riff.available() != 0) {
306
int opcode = riff.readUnsignedShort();
307
switch (opcode) {
308
case DLS_CDL_AND:
309
x = stack.pop();
310
y = stack.pop();
311
stack.push(Long.valueOf(((x != 0) && (y != 0)) ? 1 : 0));
312
break;
313
case DLS_CDL_OR:
314
x = stack.pop();
315
y = stack.pop();
316
stack.push(Long.valueOf(((x != 0) || (y != 0)) ? 1 : 0));
317
break;
318
case DLS_CDL_XOR:
319
x = stack.pop();
320
y = stack.pop();
321
stack.push(Long.valueOf(((x != 0) ^ (y != 0)) ? 1 : 0));
322
break;
323
case DLS_CDL_ADD:
324
x = stack.pop();
325
y = stack.pop();
326
stack.push(Long.valueOf(x + y));
327
break;
328
case DLS_CDL_SUBTRACT:
329
x = stack.pop();
330
y = stack.pop();
331
stack.push(Long.valueOf(x - y));
332
break;
333
case DLS_CDL_MULTIPLY:
334
x = stack.pop();
335
y = stack.pop();
336
stack.push(Long.valueOf(x * y));
337
break;
338
case DLS_CDL_DIVIDE:
339
x = stack.pop();
340
y = stack.pop();
341
stack.push(Long.valueOf(x / y));
342
break;
343
case DLS_CDL_LOGICAL_AND:
344
x = stack.pop();
345
y = stack.pop();
346
stack.push(Long.valueOf(((x != 0) && (y != 0)) ? 1 : 0));
347
break;
348
case DLS_CDL_LOGICAL_OR:
349
x = stack.pop();
350
y = stack.pop();
351
stack.push(Long.valueOf(((x != 0) || (y != 0)) ? 1 : 0));
352
break;
353
case DLS_CDL_LT:
354
x = stack.pop();
355
y = stack.pop();
356
stack.push(Long.valueOf((x < y) ? 1 : 0));
357
break;
358
case DLS_CDL_LE:
359
x = stack.pop();
360
y = stack.pop();
361
stack.push(Long.valueOf((x <= y) ? 1 : 0));
362
break;
363
case DLS_CDL_GT:
364
x = stack.pop();
365
y = stack.pop();
366
stack.push(Long.valueOf((x > y) ? 1 : 0));
367
break;
368
case DLS_CDL_GE:
369
x = stack.pop();
370
y = stack.pop();
371
stack.push(Long.valueOf((x >= y) ? 1 : 0));
372
break;
373
case DLS_CDL_EQ:
374
x = stack.pop();
375
y = stack.pop();
376
stack.push(Long.valueOf((x == y) ? 1 : 0));
377
break;
378
case DLS_CDL_NOT:
379
x = stack.pop();
380
y = stack.pop();
381
stack.push(Long.valueOf((x == 0) ? 1 : 0));
382
break;
383
case DLS_CDL_CONST:
384
stack.push(Long.valueOf(riff.readUnsignedInt()));
385
break;
386
case DLS_CDL_QUERY:
387
uuid = DLSID.read(riff);
388
stack.push(cdlQuery(uuid));
389
break;
390
case DLS_CDL_QUERYSUPPORTED:
391
uuid = DLSID.read(riff);
392
stack.push(Long.valueOf(cdlIsQuerySupported(uuid) ? 1 : 0));
393
break;
394
default:
395
break;
396
}
397
}
398
if (stack.isEmpty())
399
return false;
400
401
return stack.pop() == 1;
402
}
403
404
private void readInfoChunk(RIFFReader riff) throws IOException {
405
info.name = null;
406
while (riff.hasNextChunk()) {
407
RIFFReader chunk = riff.nextChunk();
408
String format = chunk.getFormat();
409
if (format.equals("INAM"))
410
info.name = chunk.readString(chunk.available());
411
else if (format.equals("ICRD"))
412
info.creationDate = chunk.readString(chunk.available());
413
else if (format.equals("IENG"))
414
info.engineers = chunk.readString(chunk.available());
415
else if (format.equals("IPRD"))
416
info.product = chunk.readString(chunk.available());
417
else if (format.equals("ICOP"))
418
info.copyright = chunk.readString(chunk.available());
419
else if (format.equals("ICMT"))
420
info.comments = chunk.readString(chunk.available());
421
else if (format.equals("ISFT"))
422
info.tools = chunk.readString(chunk.available());
423
else if (format.equals("IARL"))
424
info.archival_location = chunk.readString(chunk.available());
425
else if (format.equals("IART"))
426
info.artist = chunk.readString(chunk.available());
427
else if (format.equals("ICMS"))
428
info.commissioned = chunk.readString(chunk.available());
429
else if (format.equals("IGNR"))
430
info.genre = chunk.readString(chunk.available());
431
else if (format.equals("IKEY"))
432
info.keywords = chunk.readString(chunk.available());
433
else if (format.equals("IMED"))
434
info.medium = chunk.readString(chunk.available());
435
else if (format.equals("ISBJ"))
436
info.subject = chunk.readString(chunk.available());
437
else if (format.equals("ISRC"))
438
info.source = chunk.readString(chunk.available());
439
else if (format.equals("ISRF"))
440
info.source_form = chunk.readString(chunk.available());
441
else if (format.equals("ITCH"))
442
info.technician = chunk.readString(chunk.available());
443
}
444
}
445
446
private void readLinsChunk(RIFFReader riff) throws IOException {
447
while (riff.hasNextChunk()) {
448
RIFFReader chunk = riff.nextChunk();
449
if (chunk.getFormat().equals("LIST")) {
450
if (chunk.getType().equals("ins "))
451
readInsChunk(chunk);
452
}
453
}
454
}
455
456
private void readInsChunk(RIFFReader riff) throws IOException {
457
DLSInstrument instrument = new DLSInstrument(this);
458
459
while (riff.hasNextChunk()) {
460
RIFFReader chunk = riff.nextChunk();
461
String format = chunk.getFormat();
462
if (format.equals("LIST")) {
463
if (chunk.getType().equals("INFO")) {
464
readInsInfoChunk(instrument, chunk);
465
}
466
if (chunk.getType().equals("lrgn")) {
467
while (chunk.hasNextChunk()) {
468
RIFFReader subchunk = chunk.nextChunk();
469
if (subchunk.getFormat().equals("LIST")) {
470
if (subchunk.getType().equals("rgn ")) {
471
DLSRegion split = new DLSRegion();
472
if (readRgnChunk(split, subchunk))
473
instrument.getRegions().add(split);
474
}
475
if (subchunk.getType().equals("rgn2")) {
476
// support for DLS level 2 regions
477
DLSRegion split = new DLSRegion();
478
if (readRgnChunk(split, subchunk))
479
instrument.getRegions().add(split);
480
}
481
}
482
}
483
}
484
if (chunk.getType().equals("lart")) {
485
List<DLSModulator> modlist = new ArrayList<DLSModulator>();
486
while (chunk.hasNextChunk()) {
487
RIFFReader subchunk = chunk.nextChunk();
488
if (chunk.getFormat().equals("cdl ")) {
489
if (!readCdlChunk(chunk)) {
490
modlist.clear();
491
break;
492
}
493
}
494
if (subchunk.getFormat().equals("art1"))
495
readArt1Chunk(modlist, subchunk);
496
}
497
instrument.getModulators().addAll(modlist);
498
}
499
if (chunk.getType().equals("lar2")) {
500
// support for DLS level 2 ART
501
List<DLSModulator> modlist = new ArrayList<DLSModulator>();
502
while (chunk.hasNextChunk()) {
503
RIFFReader subchunk = chunk.nextChunk();
504
if (chunk.getFormat().equals("cdl ")) {
505
if (!readCdlChunk(chunk)) {
506
modlist.clear();
507
break;
508
}
509
}
510
if (subchunk.getFormat().equals("art2"))
511
readArt2Chunk(modlist, subchunk);
512
}
513
instrument.getModulators().addAll(modlist);
514
}
515
} else {
516
if (format.equals("dlid")) {
517
instrument.guid = new byte[16];
518
chunk.readFully(instrument.guid);
519
}
520
if (format.equals("insh")) {
521
chunk.readUnsignedInt(); // Read Region Count - ignored
522
523
int bank = chunk.read(); // LSB
524
bank += (chunk.read() & 127) << 7; // MSB
525
chunk.read(); // Read Reserved byte
526
int drumins = chunk.read(); // Drum Instrument
527
528
int id = chunk.read() & 127; // Read only first 7 bits
529
chunk.read(); // Read Reserved byte
530
chunk.read(); // Read Reserved byte
531
chunk.read(); // Read Reserved byte
532
533
instrument.bank = bank;
534
instrument.preset = (int) id;
535
instrument.druminstrument = (drumins & 128) > 0;
536
//System.out.println("bank="+bank+" drumkit="+drumkit
537
// +" id="+id);
538
}
539
540
}
541
}
542
instruments.add(instrument);
543
}
544
545
private void readArt1Chunk(List<DLSModulator> modulators, RIFFReader riff)
546
throws IOException {
547
long size = riff.readUnsignedInt();
548
long count = riff.readUnsignedInt();
549
550
if (size - 8 != 0)
551
riff.skip(size - 8);
552
553
for (int i = 0; i < count; i++) {
554
DLSModulator modulator = new DLSModulator();
555
modulator.version = 1;
556
modulator.source = riff.readUnsignedShort();
557
modulator.control = riff.readUnsignedShort();
558
modulator.destination = riff.readUnsignedShort();
559
modulator.transform = riff.readUnsignedShort();
560
modulator.scale = riff.readInt();
561
modulators.add(modulator);
562
}
563
}
564
565
private void readArt2Chunk(List<DLSModulator> modulators, RIFFReader riff)
566
throws IOException {
567
long size = riff.readUnsignedInt();
568
long count = riff.readUnsignedInt();
569
570
if (size - 8 != 0)
571
riff.skip(size - 8);
572
573
for (int i = 0; i < count; i++) {
574
DLSModulator modulator = new DLSModulator();
575
modulator.version = 2;
576
modulator.source = riff.readUnsignedShort();
577
modulator.control = riff.readUnsignedShort();
578
modulator.destination = riff.readUnsignedShort();
579
modulator.transform = riff.readUnsignedShort();
580
modulator.scale = riff.readInt();
581
modulators.add(modulator);
582
}
583
}
584
585
private Map<DLSRegion, Long> temp_rgnassign = new HashMap<DLSRegion, Long>();
586
587
private boolean readRgnChunk(DLSRegion split, RIFFReader riff)
588
throws IOException {
589
while (riff.hasNextChunk()) {
590
RIFFReader chunk = riff.nextChunk();
591
String format = chunk.getFormat();
592
if (format.equals("LIST")) {
593
if (chunk.getType().equals("lart")) {
594
List<DLSModulator> modlist = new ArrayList<DLSModulator>();
595
while (chunk.hasNextChunk()) {
596
RIFFReader subchunk = chunk.nextChunk();
597
if (chunk.getFormat().equals("cdl ")) {
598
if (!readCdlChunk(chunk)) {
599
modlist.clear();
600
break;
601
}
602
}
603
if (subchunk.getFormat().equals("art1"))
604
readArt1Chunk(modlist, subchunk);
605
}
606
split.getModulators().addAll(modlist);
607
}
608
if (chunk.getType().equals("lar2")) {
609
// support for DLS level 2 ART
610
List<DLSModulator> modlist = new ArrayList<DLSModulator>();
611
while (chunk.hasNextChunk()) {
612
RIFFReader subchunk = chunk.nextChunk();
613
if (chunk.getFormat().equals("cdl ")) {
614
if (!readCdlChunk(chunk)) {
615
modlist.clear();
616
break;
617
}
618
}
619
if (subchunk.getFormat().equals("art2"))
620
readArt2Chunk(modlist, subchunk);
621
}
622
split.getModulators().addAll(modlist);
623
}
624
} else {
625
626
if (format.equals("cdl ")) {
627
if (!readCdlChunk(chunk))
628
return false;
629
}
630
if (format.equals("rgnh")) {
631
split.keyfrom = chunk.readUnsignedShort();
632
split.keyto = chunk.readUnsignedShort();
633
split.velfrom = chunk.readUnsignedShort();
634
split.velto = chunk.readUnsignedShort();
635
split.options = chunk.readUnsignedShort();
636
split.exclusiveClass = chunk.readUnsignedShort();
637
}
638
if (format.equals("wlnk")) {
639
split.fusoptions = chunk.readUnsignedShort();
640
split.phasegroup = chunk.readUnsignedShort();
641
split.channel = chunk.readUnsignedInt();
642
long sampleid = chunk.readUnsignedInt();
643
temp_rgnassign.put(split, sampleid);
644
}
645
if (format.equals("wsmp")) {
646
split.sampleoptions = new DLSSampleOptions();
647
readWsmpChunk(split.sampleoptions, chunk);
648
}
649
}
650
}
651
return true;
652
}
653
654
private void readWsmpChunk(DLSSampleOptions sampleOptions, RIFFReader riff)
655
throws IOException {
656
long size = riff.readUnsignedInt();
657
sampleOptions.unitynote = riff.readUnsignedShort();
658
sampleOptions.finetune = riff.readShort();
659
sampleOptions.attenuation = riff.readInt();
660
sampleOptions.options = riff.readUnsignedInt();
661
long loops = riff.readInt();
662
663
if (size > 20)
664
riff.skip(size - 20);
665
666
for (int i = 0; i < loops; i++) {
667
DLSSampleLoop loop = new DLSSampleLoop();
668
long size2 = riff.readUnsignedInt();
669
loop.type = riff.readUnsignedInt();
670
loop.start = riff.readUnsignedInt();
671
loop.length = riff.readUnsignedInt();
672
sampleOptions.loops.add(loop);
673
if (size2 > 16)
674
riff.skip(size2 - 16);
675
}
676
}
677
678
private void readInsInfoChunk(DLSInstrument dlsinstrument, RIFFReader riff)
679
throws IOException {
680
dlsinstrument.info.name = null;
681
while (riff.hasNextChunk()) {
682
RIFFReader chunk = riff.nextChunk();
683
String format = chunk.getFormat();
684
if (format.equals("INAM")) {
685
dlsinstrument.info.name = chunk.readString(chunk.available());
686
} else if (format.equals("ICRD")) {
687
dlsinstrument.info.creationDate =
688
chunk.readString(chunk.available());
689
} else if (format.equals("IENG")) {
690
dlsinstrument.info.engineers =
691
chunk.readString(chunk.available());
692
} else if (format.equals("IPRD")) {
693
dlsinstrument.info.product = chunk.readString(chunk.available());
694
} else if (format.equals("ICOP")) {
695
dlsinstrument.info.copyright =
696
chunk.readString(chunk.available());
697
} else if (format.equals("ICMT")) {
698
dlsinstrument.info.comments =
699
chunk.readString(chunk.available());
700
} else if (format.equals("ISFT")) {
701
dlsinstrument.info.tools = chunk.readString(chunk.available());
702
} else if (format.equals("IARL")) {
703
dlsinstrument.info.archival_location =
704
chunk.readString(chunk.available());
705
} else if (format.equals("IART")) {
706
dlsinstrument.info.artist = chunk.readString(chunk.available());
707
} else if (format.equals("ICMS")) {
708
dlsinstrument.info.commissioned =
709
chunk.readString(chunk.available());
710
} else if (format.equals("IGNR")) {
711
dlsinstrument.info.genre = chunk.readString(chunk.available());
712
} else if (format.equals("IKEY")) {
713
dlsinstrument.info.keywords =
714
chunk.readString(chunk.available());
715
} else if (format.equals("IMED")) {
716
dlsinstrument.info.medium = chunk.readString(chunk.available());
717
} else if (format.equals("ISBJ")) {
718
dlsinstrument.info.subject = chunk.readString(chunk.available());
719
} else if (format.equals("ISRC")) {
720
dlsinstrument.info.source = chunk.readString(chunk.available());
721
} else if (format.equals("ISRF")) {
722
dlsinstrument.info.source_form =
723
chunk.readString(chunk.available());
724
} else if (format.equals("ITCH")) {
725
dlsinstrument.info.technician =
726
chunk.readString(chunk.available());
727
}
728
}
729
}
730
731
private void readWvplChunk(RIFFReader riff) throws IOException {
732
while (riff.hasNextChunk()) {
733
RIFFReader chunk = riff.nextChunk();
734
if (chunk.getFormat().equals("LIST")) {
735
if (chunk.getType().equals("wave"))
736
readWaveChunk(chunk);
737
}
738
}
739
}
740
741
private void readWaveChunk(RIFFReader riff) throws IOException {
742
DLSSample sample = new DLSSample(this);
743
744
while (riff.hasNextChunk()) {
745
RIFFReader chunk = riff.nextChunk();
746
String format = chunk.getFormat();
747
if (format.equals("LIST")) {
748
if (chunk.getType().equals("INFO")) {
749
readWaveInfoChunk(sample, chunk);
750
}
751
} else {
752
if (format.equals("dlid")) {
753
sample.guid = new byte[16];
754
chunk.readFully(sample.guid);
755
}
756
757
if (format.equals("fmt ")) {
758
int sampleformat = chunk.readUnsignedShort();
759
if (sampleformat != 1 && sampleformat != 3) {
760
throw new RIFFInvalidDataException(
761
"Only PCM samples are supported!");
762
}
763
int channels = chunk.readUnsignedShort();
764
long samplerate = chunk.readUnsignedInt();
765
// bytes per sec
766
/* long framerate = */ chunk.readUnsignedInt();
767
// block align, framesize
768
int framesize = chunk.readUnsignedShort();
769
int bits = chunk.readUnsignedShort();
770
AudioFormat audioformat = null;
771
if (sampleformat == 1) {
772
if (bits == 8) {
773
audioformat = new AudioFormat(
774
Encoding.PCM_UNSIGNED, samplerate, bits,
775
channels, framesize, samplerate, false);
776
} else {
777
audioformat = new AudioFormat(
778
Encoding.PCM_SIGNED, samplerate, bits,
779
channels, framesize, samplerate, false);
780
}
781
}
782
if (sampleformat == 3) {
783
audioformat = new AudioFormat(
784
Encoding.PCM_FLOAT, samplerate, bits,
785
channels, framesize, samplerate, false);
786
}
787
788
sample.format = audioformat;
789
}
790
791
if (format.equals("data")) {
792
if (largeFormat) {
793
sample.setData(new ModelByteBuffer(sampleFile,
794
chunk.getFilePointer(), chunk.available()));
795
} else {
796
byte[] buffer = new byte[chunk.available()];
797
// chunk.read(buffer);
798
sample.setData(buffer);
799
800
int read = 0;
801
int avail = chunk.available();
802
while (read != avail) {
803
if (avail - read > 65536) {
804
chunk.readFully(buffer, read, 65536);
805
read += 65536;
806
} else {
807
chunk.readFully(buffer, read, avail - read);
808
read = avail;
809
}
810
}
811
}
812
}
813
814
if (format.equals("wsmp")) {
815
sample.sampleoptions = new DLSSampleOptions();
816
readWsmpChunk(sample.sampleoptions, chunk);
817
}
818
}
819
}
820
821
samples.add(sample);
822
823
}
824
825
private void readWaveInfoChunk(DLSSample dlssample, RIFFReader riff)
826
throws IOException {
827
dlssample.info.name = null;
828
while (riff.hasNextChunk()) {
829
RIFFReader chunk = riff.nextChunk();
830
String format = chunk.getFormat();
831
if (format.equals("INAM")) {
832
dlssample.info.name = chunk.readString(chunk.available());
833
} else if (format.equals("ICRD")) {
834
dlssample.info.creationDate =
835
chunk.readString(chunk.available());
836
} else if (format.equals("IENG")) {
837
dlssample.info.engineers = chunk.readString(chunk.available());
838
} else if (format.equals("IPRD")) {
839
dlssample.info.product = chunk.readString(chunk.available());
840
} else if (format.equals("ICOP")) {
841
dlssample.info.copyright = chunk.readString(chunk.available());
842
} else if (format.equals("ICMT")) {
843
dlssample.info.comments = chunk.readString(chunk.available());
844
} else if (format.equals("ISFT")) {
845
dlssample.info.tools = chunk.readString(chunk.available());
846
} else if (format.equals("IARL")) {
847
dlssample.info.archival_location =
848
chunk.readString(chunk.available());
849
} else if (format.equals("IART")) {
850
dlssample.info.artist = chunk.readString(chunk.available());
851
} else if (format.equals("ICMS")) {
852
dlssample.info.commissioned =
853
chunk.readString(chunk.available());
854
} else if (format.equals("IGNR")) {
855
dlssample.info.genre = chunk.readString(chunk.available());
856
} else if (format.equals("IKEY")) {
857
dlssample.info.keywords = chunk.readString(chunk.available());
858
} else if (format.equals("IMED")) {
859
dlssample.info.medium = chunk.readString(chunk.available());
860
} else if (format.equals("ISBJ")) {
861
dlssample.info.subject = chunk.readString(chunk.available());
862
} else if (format.equals("ISRC")) {
863
dlssample.info.source = chunk.readString(chunk.available());
864
} else if (format.equals("ISRF")) {
865
dlssample.info.source_form = chunk.readString(chunk.available());
866
} else if (format.equals("ITCH")) {
867
dlssample.info.technician = chunk.readString(chunk.available());
868
}
869
}
870
}
871
872
public void save(String name) throws IOException {
873
writeSoundbank(new RIFFWriter(name, "DLS "));
874
}
875
876
public void save(File file) throws IOException {
877
writeSoundbank(new RIFFWriter(file, "DLS "));
878
}
879
880
public void save(OutputStream out) throws IOException {
881
writeSoundbank(new RIFFWriter(out, "DLS "));
882
}
883
884
private void writeSoundbank(RIFFWriter writer) throws IOException {
885
RIFFWriter colh_chunk = writer.writeChunk("colh");
886
colh_chunk.writeUnsignedInt(instruments.size());
887
888
if (major != -1 && minor != -1) {
889
RIFFWriter vers_chunk = writer.writeChunk("vers");
890
vers_chunk.writeUnsignedInt(major);
891
vers_chunk.writeUnsignedInt(minor);
892
}
893
894
writeInstruments(writer.writeList("lins"));
895
896
RIFFWriter ptbl = writer.writeChunk("ptbl");
897
ptbl.writeUnsignedInt(8);
898
ptbl.writeUnsignedInt(samples.size());
899
long ptbl_offset = writer.getFilePointer();
900
for (int i = 0; i < samples.size(); i++)
901
ptbl.writeUnsignedInt(0);
902
903
RIFFWriter wvpl = writer.writeList("wvpl");
904
long off = wvpl.getFilePointer();
905
List<Long> offsettable = new ArrayList<Long>();
906
for (DLSSample sample : samples) {
907
offsettable.add(Long.valueOf(wvpl.getFilePointer() - off));
908
writeSample(wvpl.writeList("wave"), sample);
909
}
910
911
// small cheat, we are going to rewrite data back in wvpl
912
long bak = writer.getFilePointer();
913
writer.seek(ptbl_offset);
914
writer.setWriteOverride(true);
915
for (Long offset : offsettable)
916
writer.writeUnsignedInt(offset.longValue());
917
writer.setWriteOverride(false);
918
writer.seek(bak);
919
920
writeInfo(writer.writeList("INFO"), info);
921
922
writer.close();
923
}
924
925
private void writeSample(RIFFWriter writer, DLSSample sample)
926
throws IOException {
927
928
AudioFormat audioformat = sample.getFormat();
929
930
Encoding encoding = audioformat.getEncoding();
931
float sampleRate = audioformat.getSampleRate();
932
int sampleSizeInBits = audioformat.getSampleSizeInBits();
933
int channels = audioformat.getChannels();
934
int frameSize = audioformat.getFrameSize();
935
float frameRate = audioformat.getFrameRate();
936
boolean bigEndian = audioformat.isBigEndian();
937
938
boolean convert_needed = false;
939
940
if (audioformat.getSampleSizeInBits() == 8) {
941
if (!encoding.equals(Encoding.PCM_UNSIGNED)) {
942
encoding = Encoding.PCM_UNSIGNED;
943
convert_needed = true;
944
}
945
} else {
946
if (!encoding.equals(Encoding.PCM_SIGNED)) {
947
encoding = Encoding.PCM_SIGNED;
948
convert_needed = true;
949
}
950
if (bigEndian) {
951
bigEndian = false;
952
convert_needed = true;
953
}
954
}
955
956
if (convert_needed) {
957
audioformat = new AudioFormat(encoding, sampleRate,
958
sampleSizeInBits, channels, frameSize, frameRate, bigEndian);
959
}
960
961
// fmt
962
RIFFWriter fmt_chunk = writer.writeChunk("fmt ");
963
int sampleformat = 0;
964
if (audioformat.getEncoding().equals(Encoding.PCM_UNSIGNED))
965
sampleformat = 1;
966
else if (audioformat.getEncoding().equals(Encoding.PCM_SIGNED))
967
sampleformat = 1;
968
else if (audioformat.getEncoding().equals(Encoding.PCM_FLOAT))
969
sampleformat = 3;
970
971
fmt_chunk.writeUnsignedShort(sampleformat);
972
fmt_chunk.writeUnsignedShort(audioformat.getChannels());
973
fmt_chunk.writeUnsignedInt((long) audioformat.getSampleRate());
974
long srate = ((long)audioformat.getFrameRate())*audioformat.getFrameSize();
975
fmt_chunk.writeUnsignedInt(srate);
976
fmt_chunk.writeUnsignedShort(audioformat.getFrameSize());
977
fmt_chunk.writeUnsignedShort(audioformat.getSampleSizeInBits());
978
fmt_chunk.write(0);
979
fmt_chunk.write(0);
980
981
writeSampleOptions(writer.writeChunk("wsmp"), sample.sampleoptions);
982
983
if (convert_needed) {
984
RIFFWriter data_chunk = writer.writeChunk("data");
985
AudioInputStream stream = AudioSystem.getAudioInputStream(
986
audioformat, (AudioInputStream)sample.getData());
987
byte[] buff = new byte[1024];
988
int ret;
989
while ((ret = stream.read(buff)) != -1) {
990
data_chunk.write(buff, 0, ret);
991
}
992
} else {
993
RIFFWriter data_chunk = writer.writeChunk("data");
994
ModelByteBuffer databuff = sample.getDataBuffer();
995
databuff.writeTo(data_chunk);
996
/*
997
data_chunk.write(databuff.array(),
998
databuff.arrayOffset(),
999
databuff.capacity());
1000
*/
1001
}
1002
1003
writeInfo(writer.writeList("INFO"), sample.info);
1004
}
1005
1006
private void writeInstruments(RIFFWriter writer) throws IOException {
1007
for (DLSInstrument instrument : instruments) {
1008
writeInstrument(writer.writeList("ins "), instrument);
1009
}
1010
}
1011
1012
private void writeInstrument(RIFFWriter writer, DLSInstrument instrument)
1013
throws IOException {
1014
1015
int art1_count = 0;
1016
int art2_count = 0;
1017
for (DLSModulator modulator : instrument.getModulators()) {
1018
if (modulator.version == 1)
1019
art1_count++;
1020
if (modulator.version == 2)
1021
art2_count++;
1022
}
1023
for (DLSRegion region : instrument.regions) {
1024
for (DLSModulator modulator : region.getModulators()) {
1025
if (modulator.version == 1)
1026
art1_count++;
1027
if (modulator.version == 2)
1028
art2_count++;
1029
}
1030
}
1031
1032
int version = 1;
1033
if (art2_count > 0)
1034
version = 2;
1035
1036
RIFFWriter insh_chunk = writer.writeChunk("insh");
1037
insh_chunk.writeUnsignedInt(instrument.getRegions().size());
1038
insh_chunk.writeUnsignedInt(instrument.bank +
1039
(instrument.druminstrument ? 2147483648L : 0));
1040
insh_chunk.writeUnsignedInt(instrument.preset);
1041
1042
RIFFWriter lrgn = writer.writeList("lrgn");
1043
for (DLSRegion region: instrument.regions)
1044
writeRegion(lrgn, region, version);
1045
1046
writeArticulators(writer, instrument.getModulators());
1047
1048
writeInfo(writer.writeList("INFO"), instrument.info);
1049
1050
}
1051
1052
private void writeArticulators(RIFFWriter writer,
1053
List<DLSModulator> modulators) throws IOException {
1054
int art1_count = 0;
1055
int art2_count = 0;
1056
for (DLSModulator modulator : modulators) {
1057
if (modulator.version == 1)
1058
art1_count++;
1059
if (modulator.version == 2)
1060
art2_count++;
1061
}
1062
if (art1_count > 0) {
1063
RIFFWriter lar1 = writer.writeList("lart");
1064
RIFFWriter art1 = lar1.writeChunk("art1");
1065
art1.writeUnsignedInt(8);
1066
art1.writeUnsignedInt(art1_count);
1067
for (DLSModulator modulator : modulators) {
1068
if (modulator.version == 1) {
1069
art1.writeUnsignedShort(modulator.source);
1070
art1.writeUnsignedShort(modulator.control);
1071
art1.writeUnsignedShort(modulator.destination);
1072
art1.writeUnsignedShort(modulator.transform);
1073
art1.writeInt(modulator.scale);
1074
}
1075
}
1076
}
1077
if (art2_count > 0) {
1078
RIFFWriter lar2 = writer.writeList("lar2");
1079
RIFFWriter art2 = lar2.writeChunk("art2");
1080
art2.writeUnsignedInt(8);
1081
art2.writeUnsignedInt(art2_count);
1082
for (DLSModulator modulator : modulators) {
1083
if (modulator.version == 2) {
1084
art2.writeUnsignedShort(modulator.source);
1085
art2.writeUnsignedShort(modulator.control);
1086
art2.writeUnsignedShort(modulator.destination);
1087
art2.writeUnsignedShort(modulator.transform);
1088
art2.writeInt(modulator.scale);
1089
}
1090
}
1091
}
1092
}
1093
1094
private void writeRegion(RIFFWriter writer, DLSRegion region, int version)
1095
throws IOException {
1096
RIFFWriter rgns = null;
1097
if (version == 1)
1098
rgns = writer.writeList("rgn ");
1099
if (version == 2)
1100
rgns = writer.writeList("rgn2");
1101
if (rgns == null)
1102
return;
1103
1104
RIFFWriter rgnh = rgns.writeChunk("rgnh");
1105
rgnh.writeUnsignedShort(region.keyfrom);
1106
rgnh.writeUnsignedShort(region.keyto);
1107
rgnh.writeUnsignedShort(region.velfrom);
1108
rgnh.writeUnsignedShort(region.velto);
1109
rgnh.writeUnsignedShort(region.options);
1110
rgnh.writeUnsignedShort(region.exclusiveClass);
1111
1112
if (region.sampleoptions != null)
1113
writeSampleOptions(rgns.writeChunk("wsmp"), region.sampleoptions);
1114
1115
if (region.sample != null) {
1116
if (samples.indexOf(region.sample) != -1) {
1117
RIFFWriter wlnk = rgns.writeChunk("wlnk");
1118
wlnk.writeUnsignedShort(region.fusoptions);
1119
wlnk.writeUnsignedShort(region.phasegroup);
1120
wlnk.writeUnsignedInt(region.channel);
1121
wlnk.writeUnsignedInt(samples.indexOf(region.sample));
1122
}
1123
}
1124
writeArticulators(rgns, region.getModulators());
1125
rgns.close();
1126
}
1127
1128
private void writeSampleOptions(RIFFWriter wsmp,
1129
DLSSampleOptions sampleoptions) throws IOException {
1130
wsmp.writeUnsignedInt(20);
1131
wsmp.writeUnsignedShort(sampleoptions.unitynote);
1132
wsmp.writeShort(sampleoptions.finetune);
1133
wsmp.writeInt(sampleoptions.attenuation);
1134
wsmp.writeUnsignedInt(sampleoptions.options);
1135
wsmp.writeInt(sampleoptions.loops.size());
1136
1137
for (DLSSampleLoop loop : sampleoptions.loops) {
1138
wsmp.writeUnsignedInt(16);
1139
wsmp.writeUnsignedInt(loop.type);
1140
wsmp.writeUnsignedInt(loop.start);
1141
wsmp.writeUnsignedInt(loop.length);
1142
}
1143
}
1144
1145
private void writeInfoStringChunk(RIFFWriter writer,
1146
String name, String value) throws IOException {
1147
if (value == null)
1148
return;
1149
RIFFWriter chunk = writer.writeChunk(name);
1150
chunk.writeString(value);
1151
int len = value.getBytes("ascii").length;
1152
chunk.write(0);
1153
len++;
1154
if (len % 2 != 0)
1155
chunk.write(0);
1156
}
1157
1158
private void writeInfo(RIFFWriter writer, DLSInfo info) throws IOException {
1159
writeInfoStringChunk(writer, "INAM", info.name);
1160
writeInfoStringChunk(writer, "ICRD", info.creationDate);
1161
writeInfoStringChunk(writer, "IENG", info.engineers);
1162
writeInfoStringChunk(writer, "IPRD", info.product);
1163
writeInfoStringChunk(writer, "ICOP", info.copyright);
1164
writeInfoStringChunk(writer, "ICMT", info.comments);
1165
writeInfoStringChunk(writer, "ISFT", info.tools);
1166
writeInfoStringChunk(writer, "IARL", info.archival_location);
1167
writeInfoStringChunk(writer, "IART", info.artist);
1168
writeInfoStringChunk(writer, "ICMS", info.commissioned);
1169
writeInfoStringChunk(writer, "IGNR", info.genre);
1170
writeInfoStringChunk(writer, "IKEY", info.keywords);
1171
writeInfoStringChunk(writer, "IMED", info.medium);
1172
writeInfoStringChunk(writer, "ISBJ", info.subject);
1173
writeInfoStringChunk(writer, "ISRC", info.source);
1174
writeInfoStringChunk(writer, "ISRF", info.source_form);
1175
writeInfoStringChunk(writer, "ITCH", info.technician);
1176
}
1177
1178
public DLSInfo getInfo() {
1179
return info;
1180
}
1181
1182
public String getName() {
1183
return info.name;
1184
}
1185
1186
public String getVersion() {
1187
return major + "." + minor;
1188
}
1189
1190
public String getVendor() {
1191
return info.engineers;
1192
}
1193
1194
public String getDescription() {
1195
return info.comments;
1196
}
1197
1198
public void setName(String s) {
1199
info.name = s;
1200
}
1201
1202
public void setVendor(String s) {
1203
info.engineers = s;
1204
}
1205
1206
public void setDescription(String s) {
1207
info.comments = s;
1208
}
1209
1210
public SoundbankResource[] getResources() {
1211
SoundbankResource[] resources = new SoundbankResource[samples.size()];
1212
int j = 0;
1213
for (int i = 0; i < samples.size(); i++)
1214
resources[j++] = samples.get(i);
1215
return resources;
1216
}
1217
1218
public DLSInstrument[] getInstruments() {
1219
DLSInstrument[] inslist_array =
1220
instruments.toArray(new DLSInstrument[instruments.size()]);
1221
Arrays.sort(inslist_array, new ModelInstrumentComparator());
1222
return inslist_array;
1223
}
1224
1225
public DLSSample[] getSamples() {
1226
return samples.toArray(new DLSSample[samples.size()]);
1227
}
1228
1229
public Instrument getInstrument(Patch patch) {
1230
int program = patch.getProgram();
1231
int bank = patch.getBank();
1232
boolean percussion = false;
1233
if (patch instanceof ModelPatch)
1234
percussion = ((ModelPatch) patch).isPercussion();
1235
for (Instrument instrument : instruments) {
1236
Patch patch2 = instrument.getPatch();
1237
int program2 = patch2.getProgram();
1238
int bank2 = patch2.getBank();
1239
if (program == program2 && bank == bank2) {
1240
boolean percussion2 = false;
1241
if (patch2 instanceof ModelPatch)
1242
percussion2 = ((ModelPatch) patch2).isPercussion();
1243
if (percussion == percussion2)
1244
return instrument;
1245
}
1246
}
1247
return null;
1248
}
1249
1250
public void addResource(SoundbankResource resource) {
1251
if (resource instanceof DLSInstrument)
1252
instruments.add((DLSInstrument) resource);
1253
if (resource instanceof DLSSample)
1254
samples.add((DLSSample) resource);
1255
}
1256
1257
public void removeResource(SoundbankResource resource) {
1258
if (resource instanceof DLSInstrument)
1259
instruments.remove((DLSInstrument) resource);
1260
if (resource instanceof DLSSample)
1261
samples.remove((DLSSample) resource);
1262
}
1263
1264
public void addInstrument(DLSInstrument resource) {
1265
instruments.add(resource);
1266
}
1267
1268
public void removeInstrument(DLSInstrument resource) {
1269
instruments.remove(resource);
1270
}
1271
1272
public long getMajor() {
1273
return major;
1274
}
1275
1276
public void setMajor(long major) {
1277
this.major = major;
1278
}
1279
1280
public long getMinor() {
1281
return minor;
1282
}
1283
1284
public void setMinor(long minor) {
1285
this.minor = minor;
1286
}
1287
}
1288
1289