1287 lines · 49.5 KB · Java
RawDownload
/* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package com.sun.media.sound; import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.URL;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Stack; import javax.sound.midi.Instrument;import javax.sound.midi.Patch;import javax.sound.midi.Soundbank;import javax.sound.midi.SoundbankResource;import javax.sound.sampled.AudioFormat;import javax.sound.sampled.AudioInputStream;import javax.sound.sampled.AudioSystem;import javax.sound.sampled.AudioFormat.Encoding; /** * A DLS Level 1 and Level 2 soundbank reader (from files/url/streams). * * @author Karl Helgason */public class DLSSoundbank implements Soundbank {     static private class DLSID {        long i1;        int s1;        int s2;        int x1;        int x2;        int x3;        int x4;        int x5;        int x6;        int x7;        int x8;         private DLSID() {        }         public DLSID(long i1, int s1, int s2, int x1, int x2, int x3, int x4,                int x5, int x6, int x7, int x8) {            this.i1 = i1;            this.s1 = s1;            this.s2 = s2;            this.x1 = x1;            this.x2 = x2;            this.x3 = x3;            this.x4 = x4;            this.x5 = x5;            this.x6 = x6;            this.x7 = x7;            this.x8 = x8;        }         public static DLSID read(RIFFReader riff) throws IOException {            DLSID d = new DLSID();            d.i1 = riff.readUnsignedInt();            d.s1 = riff.readUnsignedShort();            d.s2 = riff.readUnsignedShort();            d.x1 = riff.readUnsignedByte();            d.x2 = riff.readUnsignedByte();            d.x3 = riff.readUnsignedByte();            d.x4 = riff.readUnsignedByte();            d.x5 = riff.readUnsignedByte();            d.x6 = riff.readUnsignedByte();            d.x7 = riff.readUnsignedByte();            d.x8 = riff.readUnsignedByte();            return d;        }         public int hashCode() {            return (int)i1;        }         public boolean equals(Object obj) {            if (!(obj instanceof DLSID)) {                return false;            }            DLSID t = (DLSID) obj;            return i1 == t.i1 && s1 == t.s1 && s2 == t.s2                && x1 == t.x1 && x2 == t.x2 && x3 == t.x3 && x4 == t.x4                && x5 == t.x5 && x6 == t.x6 && x7 == t.x7 && x8 == t.x8;        }    }     /** X = X & Y */    private static final int DLS_CDL_AND = 0x0001;    /** X = X | Y */    private static final int DLS_CDL_OR = 0x0002;    /** X = X ^ Y */    private static final int DLS_CDL_XOR = 0x0003;    /** X = X + Y */    private static final int DLS_CDL_ADD = 0x0004;    /** X = X - Y */    private static final int DLS_CDL_SUBTRACT = 0x0005;    /** X = X * Y */    private static final int DLS_CDL_MULTIPLY = 0x0006;    /** X = X / Y */    private static final int DLS_CDL_DIVIDE = 0x0007;    /** X = X && Y */    private static final int DLS_CDL_LOGICAL_AND = 0x0008;    /** X = X || Y */    private static final int DLS_CDL_LOGICAL_OR = 0x0009;    /** X = (X < Y) */    private static final int DLS_CDL_LT = 0x000A;    /** X = (X <= Y) */    private static final int DLS_CDL_LE = 0x000B;    /** X = (X > Y) */    private static final int DLS_CDL_GT = 0x000C;    /** X = (X >= Y) */    private static final int DLS_CDL_GE = 0x000D;    /** X = (X == Y) */    private static final int DLS_CDL_EQ = 0x000E;    /** X = !X */    private static final int DLS_CDL_NOT = 0x000F;    /** 32-bit constant */    private static final int DLS_CDL_CONST = 0x0010;    /** 32-bit value returned from query */    private static final int DLS_CDL_QUERY = 0x0011;    /** 32-bit value returned from query */    private static final int DLS_CDL_QUERYSUPPORTED = 0x0012;     private static final DLSID DLSID_GMInHardware = new DLSID(0x178f2f24,            0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);    private static final DLSID DLSID_GSInHardware = new DLSID(0x178f2f25,            0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);    private static final DLSID DLSID_XGInHardware = new DLSID(0x178f2f26,            0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);    private static final DLSID DLSID_SupportsDLS1 = new DLSID(0x178f2f27,            0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);    private static final DLSID DLSID_SupportsDLS2 = new DLSID(0xf14599e5,            0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);    private static final DLSID DLSID_SampleMemorySize = new DLSID(0x178f2f28,            0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12);    private static final DLSID DLSID_ManufacturersID = new DLSID(0xb03e1181,            0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);    private static final DLSID DLSID_ProductID = new DLSID(0xb03e1182,            0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);    private static final DLSID DLSID_SamplePlaybackRate = new DLSID(0x2a91f713,            0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8);     private long major = -1;    private long minor = -1;     private DLSInfo info = new DLSInfo();     private List<DLSInstrument> instruments = new ArrayList<DLSInstrument>();    private List<DLSSample> samples = new ArrayList<DLSSample>();     private boolean largeFormat = false;    private File sampleFile;     public DLSSoundbank() {    }     public DLSSoundbank(URL url) throws IOException {        InputStream is = url.openStream();        try {            readSoundbank(is);        } finally {            is.close();        }    }     public DLSSoundbank(File file) throws IOException {        largeFormat = true;        sampleFile = file;        InputStream is = new FileInputStream(file);        try {            readSoundbank(is);        } finally {            is.close();        }    }     public DLSSoundbank(InputStream inputstream) throws IOException {        readSoundbank(inputstream);    }     private void readSoundbank(InputStream inputstream) throws IOException {        RIFFReader riff = new RIFFReader(inputstream);        if (!riff.getFormat().equals("RIFF")) {            throw new RIFFInvalidFormatException(                    "Input stream is not a valid RIFF stream!");        }        if (!riff.getType().equals("DLS ")) {            throw new RIFFInvalidFormatException(                    "Input stream is not a valid DLS soundbank!");        }        while (riff.hasNextChunk()) {            RIFFReader chunk = riff.nextChunk();            if (chunk.getFormat().equals("LIST")) {                if (chunk.getType().equals("INFO"))                    readInfoChunk(chunk);                if (chunk.getType().equals("lins"))                    readLinsChunk(chunk);                if (chunk.getType().equals("wvpl"))                    readWvplChunk(chunk);            } else {                if (chunk.getFormat().equals("cdl ")) {                    if (!readCdlChunk(chunk)) {                        throw new RIFFInvalidFormatException(                                "DLS file isn't supported!");                    }                }                if (chunk.getFormat().equals("colh")) {                    // skipped because we will load the entire bank into memory                    // long instrumentcount = chunk.readUnsignedInt();                    // System.out.println("instrumentcount = "+ instrumentcount);                }                if (chunk.getFormat().equals("ptbl")) {                    // Pool Table Chunk                    // skipped because we will load the entire bank into memory                }                if (chunk.getFormat().equals("vers")) {                    major = chunk.readUnsignedInt();                    minor = chunk.readUnsignedInt();                }            }        }         for (Map.Entry<DLSRegion, Long> entry : temp_rgnassign.entrySet()) {            entry.getKey().sample = samples.get((int)entry.getValue().longValue());        }         temp_rgnassign = null;    }     private boolean cdlIsQuerySupported(DLSID uuid) {        return uuid.equals(DLSID_GMInHardware)            || uuid.equals(DLSID_GSInHardware)            || uuid.equals(DLSID_XGInHardware)            || uuid.equals(DLSID_SupportsDLS1)            || uuid.equals(DLSID_SupportsDLS2)            || uuid.equals(DLSID_SampleMemorySize)            || uuid.equals(DLSID_ManufacturersID)            || uuid.equals(DLSID_ProductID)            || uuid.equals(DLSID_SamplePlaybackRate);    }     private long cdlQuery(DLSID uuid) {        if (uuid.equals(DLSID_GMInHardware))            return 1;        if (uuid.equals(DLSID_GSInHardware))            return 0;        if (uuid.equals(DLSID_XGInHardware))            return 0;        if (uuid.equals(DLSID_SupportsDLS1))            return 1;        if (uuid.equals(DLSID_SupportsDLS2))            return 1;        if (uuid.equals(DLSID_SampleMemorySize))            return Runtime.getRuntime().totalMemory();        if (uuid.equals(DLSID_ManufacturersID))            return 0;        if (uuid.equals(DLSID_ProductID))            return 0;        if (uuid.equals(DLSID_SamplePlaybackRate))            return 44100;        return 0;    }      // Reading cdl-ck Chunk    // "cdl " chunk can only appear inside : DLS,lart,lar2,rgn,rgn2    private boolean readCdlChunk(RIFFReader riff) throws IOException {         DLSID uuid;        long x;        long y;        Stack<Long> stack = new Stack<Long>();         while (riff.available() != 0) {            int opcode = riff.readUnsignedShort();            switch (opcode) {            case DLS_CDL_AND:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(((x != 0) && (y != 0)) ? 1 : 0));                break;            case DLS_CDL_OR:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(((x != 0) || (y != 0)) ? 1 : 0));                break;            case DLS_CDL_XOR:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(((x != 0) ^ (y != 0)) ? 1 : 0));                break;            case DLS_CDL_ADD:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(x + y));                break;            case DLS_CDL_SUBTRACT:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(x - y));                break;            case DLS_CDL_MULTIPLY:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(x * y));                break;            case DLS_CDL_DIVIDE:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(x / y));                break;            case DLS_CDL_LOGICAL_AND:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(((x != 0) && (y != 0)) ? 1 : 0));                break;            case DLS_CDL_LOGICAL_OR:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf(((x != 0) || (y != 0)) ? 1 : 0));                break;            case DLS_CDL_LT:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf((x < y) ? 1 : 0));                break;            case DLS_CDL_LE:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf((x <= y) ? 1 : 0));                break;            case DLS_CDL_GT:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf((x > y) ? 1 : 0));                break;            case DLS_CDL_GE:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf((x >= y) ? 1 : 0));                break;            case DLS_CDL_EQ:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf((x == y) ? 1 : 0));                break;            case DLS_CDL_NOT:                x = stack.pop();                y = stack.pop();                stack.push(Long.valueOf((x == 0) ? 1 : 0));                break;            case DLS_CDL_CONST:                stack.push(Long.valueOf(riff.readUnsignedInt()));                break;            case DLS_CDL_QUERY:                uuid = DLSID.read(riff);                stack.push(cdlQuery(uuid));                break;            case DLS_CDL_QUERYSUPPORTED:                uuid = DLSID.read(riff);                stack.push(Long.valueOf(cdlIsQuerySupported(uuid) ? 1 : 0));                break;            default:                break;            }        }        if (stack.isEmpty())            return false;         return stack.pop() == 1;    }     private void readInfoChunk(RIFFReader riff) throws IOException {        info.name = null;        while (riff.hasNextChunk()) {            RIFFReader chunk = riff.nextChunk();            String format = chunk.getFormat();            if (format.equals("INAM"))                info.name = chunk.readString(chunk.available());            else if (format.equals("ICRD"))                info.creationDate = chunk.readString(chunk.available());            else if (format.equals("IENG"))                info.engineers = chunk.readString(chunk.available());            else if (format.equals("IPRD"))                info.product = chunk.readString(chunk.available());            else if (format.equals("ICOP"))                info.copyright = chunk.readString(chunk.available());            else if (format.equals("ICMT"))                info.comments = chunk.readString(chunk.available());            else if (format.equals("ISFT"))                info.tools = chunk.readString(chunk.available());            else if (format.equals("IARL"))                info.archival_location = chunk.readString(chunk.available());            else if (format.equals("IART"))                info.artist = chunk.readString(chunk.available());            else if (format.equals("ICMS"))                info.commissioned = chunk.readString(chunk.available());            else if (format.equals("IGNR"))                info.genre = chunk.readString(chunk.available());            else if (format.equals("IKEY"))                info.keywords = chunk.readString(chunk.available());            else if (format.equals("IMED"))                info.medium = chunk.readString(chunk.available());            else if (format.equals("ISBJ"))                info.subject = chunk.readString(chunk.available());            else if (format.equals("ISRC"))                info.source = chunk.readString(chunk.available());            else if (format.equals("ISRF"))                info.source_form = chunk.readString(chunk.available());            else if (format.equals("ITCH"))                info.technician = chunk.readString(chunk.available());        }    }     private void readLinsChunk(RIFFReader riff) throws IOException {        while (riff.hasNextChunk()) {            RIFFReader chunk = riff.nextChunk();            if (chunk.getFormat().equals("LIST")) {                if (chunk.getType().equals("ins "))                    readInsChunk(chunk);            }        }    }     private void readInsChunk(RIFFReader riff) throws IOException {        DLSInstrument instrument = new DLSInstrument(this);         while (riff.hasNextChunk()) {            RIFFReader chunk = riff.nextChunk();            String format = chunk.getFormat();            if (format.equals("LIST")) {                if (chunk.getType().equals("INFO")) {                    readInsInfoChunk(instrument, chunk);                }                if (chunk.getType().equals("lrgn")) {                    while (chunk.hasNextChunk()) {                        RIFFReader subchunk = chunk.nextChunk();                        if (subchunk.getFormat().equals("LIST")) {                            if (subchunk.getType().equals("rgn ")) {                                DLSRegion split = new DLSRegion();                                if (readRgnChunk(split, subchunk))                                    instrument.getRegions().add(split);                            }                            if (subchunk.getType().equals("rgn2")) {                                // support for DLS level 2 regions                                DLSRegion split = new DLSRegion();                                if (readRgnChunk(split, subchunk))                                    instrument.getRegions().add(split);                            }                        }                    }                }                if (chunk.getType().equals("lart")) {                    List<DLSModulator> modlist = new ArrayList<DLSModulator>();                    while (chunk.hasNextChunk()) {                        RIFFReader subchunk = chunk.nextChunk();                        if (chunk.getFormat().equals("cdl ")) {                            if (!readCdlChunk(chunk)) {                                modlist.clear();                                break;                            }                        }                        if (subchunk.getFormat().equals("art1"))                            readArt1Chunk(modlist, subchunk);                    }                    instrument.getModulators().addAll(modlist);                }                if (chunk.getType().equals("lar2")) {                    // support for DLS level 2 ART

Lines 1–500 of 1287.