jdk/src/share/classes/com/sun/media/sound/SoftTuning.java
changeset 1846 4a53d636e2f4
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/media/sound/SoftTuning.java	Mon Jan 19 20:11:58 2009 +0300
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.media.sound;
+
+import java.io.UnsupportedEncodingException;
+
+import javax.sound.midi.Patch;
+
+/**
+ * A tuning program container, for use with MIDI Tuning.
+ * See: http://www.midi.org
+ *
+ * @author Karl Helgason
+ */
+public class SoftTuning {
+
+    private String name = null;
+    private double[] tuning = new double[128];
+    private Patch patch = null;
+
+    public SoftTuning() {
+        name = "12-TET";
+        for (int i = 0; i < tuning.length; i++)
+            tuning[i] = i * 100;
+    }
+
+    public SoftTuning(byte[] data) {
+        for (int i = 0; i < tuning.length; i++)
+            tuning[i] = i * 100;
+        load(data);
+    }
+
+    public SoftTuning(Patch patch) {
+        this.patch = patch;
+        name = "12-TET";
+        for (int i = 0; i < tuning.length; i++)
+            tuning[i] = i * 100;
+    }
+
+    public SoftTuning(Patch patch, byte[] data) {
+        this.patch = patch;
+        for (int i = 0; i < tuning.length; i++)
+            tuning[i] = i * 100;
+        load(data);
+    }
+
+    private boolean checksumOK(byte[] data) {
+        int x = data[1] & 0xFF;
+        for (int i = 2; i < data.length - 2; i++)
+            x = x ^ (data[i] & 0xFF);
+        return (data[data.length - 2] & 0xFF) == (x & 127);
+    }
+
+    /*
+    private boolean checksumOK2(byte[] data) {
+        int x = data[1] & 0xFF; // 7E
+        x = x ^ (data[2] & 0xFF); // <device ID>
+        x = x ^ (data[4] & 0xFF); // nn
+        x = x ^ (data[5] & 0xFF); // tt
+        for (int i = 22; i < data.length - 2; i++)
+            x = x ^ (data[i] & 0xFF);
+        return (data[data.length - 2] & 0xFF) == (x & 127);
+    }
+     */
+    public void load(byte[] data) {
+        // Universal Non-Real-Time / Real-Time SysEx
+        if ((data[1] & 0xFF) == 0x7E || (data[1] & 0xFF) == 0x7F) {
+            int subid1 = data[3] & 0xFF;
+            switch (subid1) {
+            case 0x08: // MIDI Tuning Standard
+                int subid2 = data[4] & 0xFF;
+                switch (subid2) {
+                case 0x01: // BULK TUNING DUMP (NON-REAL-TIME)
+                {
+                    // http://www.midi.org/about-midi/tuning.shtml
+                    //if (!checksumOK2(data))
+                    //    break;
+                    try {
+                        name = new String(data, 6, 16, "ascii");
+                    } catch (UnsupportedEncodingException e) {
+                        name = null;
+                    }
+                    int r = 22;
+                    for (int i = 0; i < 128; i++) {
+                        int xx = data[r++] & 0xFF;
+                        int yy = data[r++] & 0xFF;
+                        int zz = data[r++] & 0xFF;
+                        if (!(xx == 127 && yy == 127 && zz == 127))
+                            tuning[i] = 100.0 *
+                                    (((xx * 16384) + (yy * 128) + zz) / 16384.0);
+                    }
+                    break;
+                }
+                case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME)
+                {
+                    // http://www.midi.org/about-midi/tuning.shtml
+                    int ll = data[6] & 0xFF;
+                    int r = 7;
+                    for (int i = 0; i < ll; i++) {
+                        int kk = data[r++] & 0xFF;
+                        int xx = data[r++] & 0xFF;
+                        int yy = data[r++] & 0xFF;
+                        int zz = data[r++] & 0xFF;
+                        if (!(xx == 127 && yy == 127 && zz == 127))
+                            tuning[kk] = 100.0*(((xx*16384) + (yy*128) + zz)/16384.0);
+                    }
+                    break;
+                }
+                case 0x04: // KEY-BASED TUNING DUMP (NON-REAL-TIME)
+                {
+                    // http://www.midi.org/about-midi/tuning_extens.shtml
+                    if (!checksumOK(data))
+                        break;
+                    try {
+                        name = new String(data, 7, 16, "ascii");
+                    } catch (UnsupportedEncodingException e) {
+                        name = null;
+                    }
+                    int r = 23;
+                    for (int i = 0; i < 128; i++) {
+                        int xx = data[r++] & 0xFF;
+                        int yy = data[r++] & 0xFF;
+                        int zz = data[r++] & 0xFF;
+                        if (!(xx == 127 && yy == 127 && zz == 127))
+                            tuning[i] = 100.0*(((xx*16384) + (yy*128) + zz)/16384.0);
+                    }
+                    break;
+                }
+                case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format
+                           // (NON-REAL-TIME)
+                {
+                    // http://www.midi.org/about-midi/tuning_extens.shtml
+                    if (!checksumOK(data))
+                        break;
+                    try {
+                        name = new String(data, 7, 16, "ascii");
+                    } catch (UnsupportedEncodingException e) {
+                        name = null;
+                    }
+                    int[] octave_tuning = new int[12];
+                    for (int i = 0; i < 12; i++)
+                        octave_tuning[i] = (data[i + 23] & 0xFF) - 64;
+                    for (int i = 0; i < tuning.length; i++)
+                        tuning[i] = i * 100 + octave_tuning[i % 12];
+                    break;
+                }
+                case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format
+                           // (NON-REAL-TIME)
+                {
+                    // http://www.midi.org/about-midi/tuning_extens.shtml
+                    if (!checksumOK(data))
+                        break;
+                    try {
+                        name = new String(data, 7, 16, "ascii");
+                    } catch (UnsupportedEncodingException e) {
+                        name = null;
+                    }
+                    double[] octave_tuning = new double[12];
+                    for (int i = 0; i < 12; i++) {
+                        int v = (data[i * 2 + 23] & 0xFF) * 128
+                                + (data[i * 2 + 24] & 0xFF);
+                        octave_tuning[i] = (v / 8192.0 - 1) * 100.0;
+                    }
+                    for (int i = 0; i < tuning.length; i++)
+                        tuning[i] = i * 100 + octave_tuning[i % 12];
+                    break;
+                }
+                case 0x07: // SINGLE NOTE TUNING CHANGE (NON
+                           // REAL-TIME/REAL-TIME) (BANK)
+                    // http://www.midi.org/about-midi/tuning_extens.shtml
+                    int ll = data[7] & 0xFF;
+                    int r = 8;
+                    for (int i = 0; i < ll; i++) {
+                        int kk = data[r++] & 0xFF;
+                        int xx = data[r++] & 0xFF;
+                        int yy = data[r++] & 0xFF;
+                        int zz = data[r++] & 0xFF;
+                        if (!(xx == 127 && yy == 127 && zz == 127))
+                            tuning[kk] = 100.0
+                                    * (((xx*16384) + (yy*128) + zz) / 16384.0);
+                    }
+                    break;
+                case 0x08: // scale/octave tuning 1-byte form (Non
+                           // Real-Time/REAL-TIME)
+                {
+                    // http://www.midi.org/about-midi/tuning-scale.shtml
+                    int[] octave_tuning = new int[12];
+                    for (int i = 0; i < 12; i++)
+                        octave_tuning[i] = (data[i + 8] & 0xFF) - 64;
+                    for (int i = 0; i < tuning.length; i++)
+                        tuning[i] = i * 100 + octave_tuning[i % 12];
+                    break;
+                }
+                case 0x09: // scale/octave tuning 2-byte form (Non
+                           // Real-Time/REAL-TIME)
+                {
+                    // http://www.midi.org/about-midi/tuning-scale.shtml
+                    double[] octave_tuning = new double[12];
+                    for (int i = 0; i < 12; i++) {
+                        int v = (data[i * 2 + 8] & 0xFF) * 128
+                                + (data[i * 2 + 9] & 0xFF);
+                        octave_tuning[i] = (v / 8192.0 - 1) * 100.0;
+                    }
+                    for (int i = 0; i < tuning.length; i++)
+                        tuning[i] = i * 100 + octave_tuning[i % 12];
+                    break;
+                }
+                default:
+                    break;
+                }
+            }
+        }
+    }
+
+    public double[] getTuning() {
+        return tuning;
+    }
+
+    public double getTuning(int noteNumber) {
+        return tuning[noteNumber];
+    }
+
+    public Patch getPatch() {
+        return patch;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}