< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/DLSSoundbank.java

Print this page




   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;
< prev index next >