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 private static 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;
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 */
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);
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:
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
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")) {
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)
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;
|
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
26 package com.sun.media.sound;
27
28 import java.io.File;
29 import java.io.FileInputStream;
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.net.URL;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.HashMap;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Stack;
40
41 import javax.sound.midi.Instrument;
42 import javax.sound.midi.Patch;
43 import javax.sound.midi.Soundbank;
44 import javax.sound.midi.SoundbankResource;
45 import javax.sound.sampled.AudioFormat;
46 import javax.sound.sampled.AudioFormat.Encoding;
47 import javax.sound.sampled.AudioInputStream;
48 import javax.sound.sampled.AudioSystem;
49
50 /**
51 * A DLS Level 1 and Level 2 soundbank reader (from files/url/streams).
52 *
53 * @author Karl Helgason
54 */
55 public final class DLSSoundbank implements Soundbank {
56
57 private static class DLSID {
58 long i1;
59 int s1;
60 int s2;
61 int x1;
62 int x2;
63 int x3;
64 int x4;
65 int x5;
66 int x6;
67 int x7;
68 int x8;
84 this.x7 = x7;
85 this.x8 = x8;
86 }
87
88 public static DLSID read(RIFFReader riff) throws IOException {
89 DLSID d = new DLSID();
90 d.i1 = riff.readUnsignedInt();
91 d.s1 = riff.readUnsignedShort();
92 d.s2 = riff.readUnsignedShort();
93 d.x1 = riff.readUnsignedByte();
94 d.x2 = riff.readUnsignedByte();
95 d.x3 = riff.readUnsignedByte();
96 d.x4 = riff.readUnsignedByte();
97 d.x5 = riff.readUnsignedByte();
98 d.x6 = riff.readUnsignedByte();
99 d.x7 = riff.readUnsignedByte();
100 d.x8 = riff.readUnsignedByte();
101 return d;
102 }
103
104 @Override
105 public int hashCode() {
106 return (int)i1;
107 }
108
109 @Override
110 public boolean equals(Object obj) {
111 if (!(obj instanceof DLSID)) {
112 return false;
113 }
114 DLSID t = (DLSID) obj;
115 return i1 == t.i1 && s1 == t.s1 && s2 == t.s2
116 && x1 == t.x1 && x2 == t.x2 && x3 == t.x3 && x4 == t.x4
117 && x5 == t.x5 && x6 == t.x6 && x7 == t.x7 && x8 == t.x8;
118 }
119 }
120
121 /** X = X & Y */
122 private static final int DLS_CDL_AND = 0x0001;
123 /** X = X | Y */
124 private static final int DLS_CDL_OR = 0x0002;
125 /** X = X ^ Y */
126 private static final int DLS_CDL_XOR = 0x0003;
127 /** X = X + Y */
128 private static final int DLS_CDL_ADD = 0x0004;
129 /** X = X - Y */
162 private static final DLSID DLSID_XGInHardware = new DLSID(0x178f2f26,
163 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
164 private static final DLSID DLSID_SupportsDLS1 = new DLSID(0x178f2f27,
165 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
166 private static final DLSID DLSID_SupportsDLS2 = new DLSID(0xf14599e5,
167 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
168 private static final DLSID DLSID_SampleMemorySize = new DLSID(0x178f2f28,
169 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);
170 private static final DLSID DLSID_ManufacturersID = new DLSID(0xb03e1181,
171 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
172 private static final DLSID DLSID_ProductID = new DLSID(0xb03e1182,
173 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
174 private static final DLSID DLSID_SamplePlaybackRate = new DLSID(0x2a91f713,
175 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);
176
177 private long major = -1;
178 private long minor = -1;
179
180 private final DLSInfo info = new DLSInfo();
181
182 private final List<DLSInstrument> instruments = new ArrayList<>();
183 private final List<DLSSample> samples = new ArrayList<>();
184
185 private boolean largeFormat = false;
186 private File sampleFile;
187
188 public DLSSoundbank() {
189 }
190
191 public DLSSoundbank(URL url) throws IOException {
192 InputStream is = url.openStream();
193 try {
194 readSoundbank(is);
195 } finally {
196 is.close();
197 }
198 }
199
200 public DLSSoundbank(File file) throws IOException {
201 largeFormat = true;
202 sampleFile = file;
203 InputStream is = new FileInputStream(file);
286 return 1;
287 if (uuid.equals(DLSID_SampleMemorySize))
288 return Runtime.getRuntime().totalMemory();
289 if (uuid.equals(DLSID_ManufacturersID))
290 return 0;
291 if (uuid.equals(DLSID_ProductID))
292 return 0;
293 if (uuid.equals(DLSID_SamplePlaybackRate))
294 return 44100;
295 return 0;
296 }
297
298
299 // Reading cdl-ck Chunk
300 // "cdl " chunk can only appear inside : DLS,lart,lar2,rgn,rgn2
301 private boolean readCdlChunk(RIFFReader riff) throws IOException {
302
303 DLSID uuid;
304 long x;
305 long y;
306 Stack<Long> stack = new Stack<>();
307
308 while (riff.available() != 0) {
309 int opcode = riff.readUnsignedShort();
310 switch (opcode) {
311 case DLS_CDL_AND:
312 x = stack.pop();
313 y = stack.pop();
314 stack.push(Long.valueOf(((x != 0) && (y != 0)) ? 1 : 0));
315 break;
316 case DLS_CDL_OR:
317 x = stack.pop();
318 y = stack.pop();
319 stack.push(Long.valueOf(((x != 0) || (y != 0)) ? 1 : 0));
320 break;
321 case DLS_CDL_XOR:
322 x = stack.pop();
323 y = stack.pop();
324 stack.push(Long.valueOf(((x != 0) ^ (y != 0)) ? 1 : 0));
325 break;
326 case DLS_CDL_ADD:
468 }
469 if (chunk.getType().equals("lrgn")) {
470 while (chunk.hasNextChunk()) {
471 RIFFReader subchunk = chunk.nextChunk();
472 if (subchunk.getFormat().equals("LIST")) {
473 if (subchunk.getType().equals("rgn ")) {
474 DLSRegion split = new DLSRegion();
475 if (readRgnChunk(split, subchunk))
476 instrument.getRegions().add(split);
477 }
478 if (subchunk.getType().equals("rgn2")) {
479 // support for DLS level 2 regions
480 DLSRegion split = new DLSRegion();
481 if (readRgnChunk(split, subchunk))
482 instrument.getRegions().add(split);
483 }
484 }
485 }
486 }
487 if (chunk.getType().equals("lart")) {
488 List<DLSModulator> modlist = new ArrayList<>();
489 while (chunk.hasNextChunk()) {
490 RIFFReader subchunk = chunk.nextChunk();
491 if (chunk.getFormat().equals("cdl ")) {
492 if (!readCdlChunk(chunk)) {
493 modlist.clear();
494 break;
495 }
496 }
497 if (subchunk.getFormat().equals("art1"))
498 readArt1Chunk(modlist, subchunk);
499 }
500 instrument.getModulators().addAll(modlist);
501 }
502 if (chunk.getType().equals("lar2")) {
503 // support for DLS level 2 ART
504 List<DLSModulator> modlist = new ArrayList<>();
505 while (chunk.hasNextChunk()) {
506 RIFFReader subchunk = chunk.nextChunk();
507 if (chunk.getFormat().equals("cdl ")) {
508 if (!readCdlChunk(chunk)) {
509 modlist.clear();
510 break;
511 }
512 }
513 if (subchunk.getFormat().equals("art2"))
514 readArt2Chunk(modlist, subchunk);
515 }
516 instrument.getModulators().addAll(modlist);
517 }
518 } else {
519 if (format.equals("dlid")) {
520 instrument.guid = new byte[16];
521 chunk.readFully(instrument.guid);
522 }
523 if (format.equals("insh")) {
524 chunk.readUnsignedInt(); // Read Region Count - ignored
568 private void readArt2Chunk(List<DLSModulator> modulators, RIFFReader riff)
569 throws IOException {
570 long size = riff.readUnsignedInt();
571 long count = riff.readUnsignedInt();
572
573 if (size - 8 != 0)
574 riff.skip(size - 8);
575
576 for (int i = 0; i < count; i++) {
577 DLSModulator modulator = new DLSModulator();
578 modulator.version = 2;
579 modulator.source = riff.readUnsignedShort();
580 modulator.control = riff.readUnsignedShort();
581 modulator.destination = riff.readUnsignedShort();
582 modulator.transform = riff.readUnsignedShort();
583 modulator.scale = riff.readInt();
584 modulators.add(modulator);
585 }
586 }
587
588 private Map<DLSRegion, Long> temp_rgnassign = new HashMap<>();
589
590 private boolean readRgnChunk(DLSRegion split, RIFFReader riff)
591 throws IOException {
592 while (riff.hasNextChunk()) {
593 RIFFReader chunk = riff.nextChunk();
594 String format = chunk.getFormat();
595 if (format.equals("LIST")) {
596 if (chunk.getType().equals("lart")) {
597 List<DLSModulator> modlist = new ArrayList<>();
598 while (chunk.hasNextChunk()) {
599 RIFFReader subchunk = chunk.nextChunk();
600 if (chunk.getFormat().equals("cdl ")) {
601 if (!readCdlChunk(chunk)) {
602 modlist.clear();
603 break;
604 }
605 }
606 if (subchunk.getFormat().equals("art1"))
607 readArt1Chunk(modlist, subchunk);
608 }
609 split.getModulators().addAll(modlist);
610 }
611 if (chunk.getType().equals("lar2")) {
612 // support for DLS level 2 ART
613 List<DLSModulator> modlist = new ArrayList<>();
614 while (chunk.hasNextChunk()) {
615 RIFFReader subchunk = chunk.nextChunk();
616 if (chunk.getFormat().equals("cdl ")) {
617 if (!readCdlChunk(chunk)) {
618 modlist.clear();
619 break;
620 }
621 }
622 if (subchunk.getFormat().equals("art2"))
623 readArt2Chunk(modlist, subchunk);
624 }
625 split.getModulators().addAll(modlist);
626 }
627 } else {
628
629 if (format.equals("cdl ")) {
630 if (!readCdlChunk(chunk))
631 return false;
632 }
633 if (format.equals("rgnh")) {
888 RIFFWriter colh_chunk = writer.writeChunk("colh");
889 colh_chunk.writeUnsignedInt(instruments.size());
890
891 if (major != -1 && minor != -1) {
892 RIFFWriter vers_chunk = writer.writeChunk("vers");
893 vers_chunk.writeUnsignedInt(major);
894 vers_chunk.writeUnsignedInt(minor);
895 }
896
897 writeInstruments(writer.writeList("lins"));
898
899 RIFFWriter ptbl = writer.writeChunk("ptbl");
900 ptbl.writeUnsignedInt(8);
901 ptbl.writeUnsignedInt(samples.size());
902 long ptbl_offset = writer.getFilePointer();
903 for (int i = 0; i < samples.size(); i++)
904 ptbl.writeUnsignedInt(0);
905
906 RIFFWriter wvpl = writer.writeList("wvpl");
907 long off = wvpl.getFilePointer();
908 List<Long> offsettable = new ArrayList<>();
909 for (DLSSample sample : samples) {
910 offsettable.add(Long.valueOf(wvpl.getFilePointer() - off));
911 writeSample(wvpl.writeList("wave"), sample);
912 }
913
914 // small cheat, we are going to rewrite data back in wvpl
915 long bak = writer.getFilePointer();
916 writer.seek(ptbl_offset);
917 writer.setWriteOverride(true);
918 for (Long offset : offsettable)
919 writer.writeUnsignedInt(offset.longValue());
920 writer.setWriteOverride(false);
921 writer.seek(bak);
922
923 writeInfo(writer.writeList("INFO"), info);
924
925 writer.close();
926 }
927
928 private void writeSample(RIFFWriter writer, DLSSample sample)
1165 writeInfoStringChunk(writer, "IPRD", info.product);
1166 writeInfoStringChunk(writer, "ICOP", info.copyright);
1167 writeInfoStringChunk(writer, "ICMT", info.comments);
1168 writeInfoStringChunk(writer, "ISFT", info.tools);
1169 writeInfoStringChunk(writer, "IARL", info.archival_location);
1170 writeInfoStringChunk(writer, "IART", info.artist);
1171 writeInfoStringChunk(writer, "ICMS", info.commissioned);
1172 writeInfoStringChunk(writer, "IGNR", info.genre);
1173 writeInfoStringChunk(writer, "IKEY", info.keywords);
1174 writeInfoStringChunk(writer, "IMED", info.medium);
1175 writeInfoStringChunk(writer, "ISBJ", info.subject);
1176 writeInfoStringChunk(writer, "ISRC", info.source);
1177 writeInfoStringChunk(writer, "ISRF", info.source_form);
1178 writeInfoStringChunk(writer, "ITCH", info.technician);
1179 }
1180
1181 public DLSInfo getInfo() {
1182 return info;
1183 }
1184
1185 @Override
1186 public String getName() {
1187 return info.name;
1188 }
1189
1190 @Override
1191 public String getVersion() {
1192 return major + "." + minor;
1193 }
1194
1195 @Override
1196 public String getVendor() {
1197 return info.engineers;
1198 }
1199
1200 @Override
1201 public String getDescription() {
1202 return info.comments;
1203 }
1204
1205 public void setName(String s) {
1206 info.name = s;
1207 }
1208
1209 public void setVendor(String s) {
1210 info.engineers = s;
1211 }
1212
1213 public void setDescription(String s) {
1214 info.comments = s;
1215 }
1216
1217 @Override
1218 public SoundbankResource[] getResources() {
1219 SoundbankResource[] resources = new SoundbankResource[samples.size()];
1220 int j = 0;
1221 for (int i = 0; i < samples.size(); i++)
1222 resources[j++] = samples.get(i);
1223 return resources;
1224 }
1225
1226 @Override
1227 public DLSInstrument[] getInstruments() {
1228 DLSInstrument[] inslist_array =
1229 instruments.toArray(new DLSInstrument[instruments.size()]);
1230 Arrays.sort(inslist_array, new ModelInstrumentComparator());
1231 return inslist_array;
1232 }
1233
1234 public DLSSample[] getSamples() {
1235 return samples.toArray(new DLSSample[samples.size()]);
1236 }
1237
1238 @Override
1239 public Instrument getInstrument(Patch patch) {
1240 int program = patch.getProgram();
1241 int bank = patch.getBank();
1242 boolean percussion = false;
1243 if (patch instanceof ModelPatch)
1244 percussion = ((ModelPatch) patch).isPercussion();
1245 for (Instrument instrument : instruments) {
1246 Patch patch2 = instrument.getPatch();
1247 int program2 = patch2.getProgram();
1248 int bank2 = patch2.getBank();
1249 if (program == program2 && bank == bank2) {
1250 boolean percussion2 = false;
1251 if (patch2 instanceof ModelPatch)
1252 percussion2 = ((ModelPatch) patch2).isPercussion();
1253 if (percussion == percussion2)
1254 return instrument;
1255 }
1256 }
1257 return null;
1258 }
1259
1260 public void addResource(SoundbankResource resource) {
1261 if (resource instanceof DLSInstrument)
1262 instruments.add((DLSInstrument) resource);
1263 if (resource instanceof DLSSample)
1264 samples.add((DLSSample) resource);
1265 }
1266
1267 public void removeResource(SoundbankResource resource) {
1268 if (resource instanceof DLSInstrument)
1269 instruments.remove(resource);
1270 if (resource instanceof DLSSample)
1271 samples.remove(resource);
1272 }
1273
1274 public void addInstrument(DLSInstrument resource) {
1275 instruments.add(resource);
1276 }
1277
1278 public void removeInstrument(DLSInstrument resource) {
1279 instruments.remove(resource);
1280 }
1281
1282 public long getMajor() {
1283 return major;
1284 }
1285
1286 public void setMajor(long major) {
1287 this.major = major;
1288 }
1289
1290 public long getMinor() {
1291 return minor;
|