Subversion Repositories svn.mios

Rev

Rev 213 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
213 tk 1
/*
2
 * @(#)SIDV2librarian.java  beta1   2008/01/21
3
 *
4
 * Copyright (C) 2008    Rutger Vlek (rutgervlek@hotmail.com)
5
 *
6
 * This application is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This application is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this application; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
 
21
package org.midibox.sidlibr;
22
 
23
import javax.sound.midi.MidiMessage;
24
import javax.sound.midi.Receiver;
25
import javax.sound.midi.SysexMessage;
628 adamjking 26
 
213 tk 27
import org.midibox.sidedit.SIDSysexInfo;
28
 
29
public class Ensemble implements Receiver {
628 adamjking 30
    private boolean[] cores = { false, false, false, false };
213 tk 31
    protected int[] ensemble = new int[256];
628 adamjking 32
 
213 tk 33
    protected Receiver receiver;
628 adamjking 34
 
213 tk 35
    public Ensemble(Receiver receiver) {
628 adamjking 36
        this.receiver = receiver;
213 tk 37
        initEnsemble();
38
    }
628 adamjking 39
 
213 tk 40
    private void initEnsemble() {
628 adamjking 41
        for (int c = 0; c < 256; c++) {
213 tk 42
            ensemble[c] = 0;
43
        }
44
        setEnsembleName("                ");
45
    }
628 adamjking 46
 
47
    public void setEnsembleName(String s) {
48
        for (int i = 0; i < 16; i++) {
49
            int value = ((int) s.charAt(i)) & 0xFF;
213 tk 50
            ensemble[i] = nibbleSwap(value);
51
            sysexSend(i, value, 1);
52
        }
53
    }
628 adamjking 54
 
55
    public String getEnsembleName() {
213 tk 56
        String s = new String("");
628 adamjking 57
        for (int i = 0; i < 16; i++) {
58
            s = s + (char) nibbleSwap(ensemble[i]);
213 tk 59
        }
628 adamjking 60
        return s;
213 tk 61
    }
628 adamjking 62
 
213 tk 63
    public String getSysexString() {
64
        String s = "";
65
        int sum = 0;
628 adamjking 66
        for (int i = 0; i < ensemble.length; i++) {
67
            String newStr = calcValue(nibbleSwap(ensemble[i]), 1);
68
            sum = sum + Integer.parseInt(newStr.substring(1, 2), 16);
69
            sum = sum + Integer.parseInt(newStr.substring(3, 4), 16);
213 tk 70
            s = s + newStr;
71
        }
72
        String checksum = Integer.toHexString(-sum & 0x7F);
628 adamjking 73
        if (checksum.length() == 1) {
213 tk 74
            checksum = "0" + checksum;
75
        }
628 adamjking 76
        return (s + checksum);
213 tk 77
    }
628 adamjking 78
 
213 tk 79
    public String parseEnsemble(String d) {
628 adamjking 80
        String status;
81
        int dsi = 20; // Index where real patch data starts
213 tk 82
        int checksum = 0;
628 adamjking 83
        for (int i = 0; i < 512; i++) {
84
            String s1 = d.substring((4 * i) + dsi + 1, (4 * i) + dsi + 2);
85
            String s2 = d.substring((4 * i) + dsi + 3, (4 * i) + dsi + 4);
86
            checksum = checksum + Integer.parseInt(s1, 16);
87
            checksum = checksum + Integer.parseInt(s2, 16);
88
            int temp = Integer.parseInt(s1 + s2, 16);
213 tk 89
            ensemble[i] = temp;
90
        }
628 adamjking 91
        int chk = Integer.parseInt(d.substring((4 * 512) + dsi, (4 * 512) + dsi
92
                + 2), 16);
213 tk 93
        if (chk != (-checksum & 0x7F)) {
94
            status = "checksum error";
628 adamjking 95
        } else {
96
            status = "succesful";
213 tk 97
        }
628 adamjking 98
        return status;
213 tk 99
    }
628 adamjking 100
 
213 tk 101
    public void setEnsemble(int[] p) {
102
        ensemble = p;
103
    }
628 adamjking 104
 
213 tk 105
    public int[] getEnsemble() {
106
        return ensemble;
107
    }
628 adamjking 108
 
213 tk 109
    public int getParameter(int address, int start_bit, int resolution) {
110
        int value = 0;
111
        int absres = Math.abs(resolution);
628 adamjking 112
 
113
        // resolution < 8 bit: gets value of bit length 'resolution' starting on
114
        // the start_bit
213 tk 115
        if (absres < 8) {
116
            int bitmask = 0;
628 adamjking 117
            for (int j = 0; j < absres; j++) { // Iterate over all bits
118
                bitmask = bitmask | (int) Math.pow(2, (start_bit + j));
119
            }
120
            value = (bitmask & nibbleSwap(ensemble[address])) >> start_bit;
213 tk 121
        }
628 adamjking 122
 
213 tk 123
        // 8 bit values
124
        if (absres == 8) {
628 adamjking 125
            value = nibbleSwap(ensemble[address]);
213 tk 126
        }
628 adamjking 127
 
213 tk 128
        // 12 bit values
129
        if (absres == 12) {
130
            int temp1 = nibbleSwap(ensemble[address]);
628 adamjking 131
            int temp2 = nibbleSwap(ensemble[address + 1] & 0xF0);
213 tk 132
            value = (temp2 << 8) + temp1;
133
        }
628 adamjking 134
 
213 tk 135
        // 16 bit values
136
        if (absres == 16) {
137
            int temp1 = nibbleSwap(ensemble[address]);
628 adamjking 138
            int temp2 = nibbleSwap(ensemble[address + 1]);
213 tk 139
            value = (temp2 << 8) + temp1;
140
        }
628 adamjking 141
 
213 tk 142
        // Shift positive integers down to make them bipolar (if required)
143
        if (resolution < 0) {
628 adamjking 144
            int midimin = -((int) Math.ceil((Math.pow(2, absres) - 1) / 2));
145
            value = value + midimin;
213 tk 146
        }
628 adamjking 147
 
213 tk 148
        return value;
149
    }
628 adamjking 150
 
151
    public void setParameter(int address, int value, int start_bit,
152
            int resolution) {
213 tk 153
        int absres = Math.abs(resolution);
628 adamjking 154
 
213 tk 155
        // Shift all bipolar values up to make them fit into a positive integer
156
        if (resolution < 0) {
628 adamjking 157
            int midimin = -((int) Math.ceil((Math.pow(2, absres) - 1) / 2));
158
            value = value - midimin;
213 tk 159
        }
628 adamjking 160
 
161
        // resolution < 8 bit: sets value of bit length 'resolution' starting on
162
        // the start_bit
163
        if (absres < 8) {
164
            int temp = nibbleSwap(ensemble[address]); // Retrieve data
165
 
166
            for (int j = 0; j < absres; j++) { // Iterate over all bits
213 tk 167
                int this_bit = start_bit + j;
628 adamjking 168
                int bitmask0 = (int) Math.pow(2, j); // Bitmask for checking if
169
                // current bit needs to
170
                // change
171
                int bitmask1 = (int) Math.pow(2, (this_bit)); // Bitmask for
172
                // turning bits
173
                // on
174
                int bitmask2 = (~bitmask1) & 0xFF; // Bitmask for turning bits
175
                // off
176
                if ((value & bitmask0) == 0) {
177
                    temp = (temp & bitmask2) & 0xFF; // Turn bit off
213 tk 178
                }
628 adamjking 179
                if ((value & bitmask0) != 0) {
180
                    temp = (temp | bitmask1) & 0xFF; // Turn bit on
181
                }
182
            }
183
            ensemble[address] = nibbleSwap(temp); // Put back new data
213 tk 184
            sysexSend(address, temp, 1);
185
        }
628 adamjking 186
 
213 tk 187
        // 8 bit values
188
        if (absres == 8) {
189
            ensemble[address] = nibbleSwap(value & 0xFF);
190
            sysexSend(address, (value & 0xFF), 1);
191
        }
628 adamjking 192
 
213 tk 193
        // 12 bit values
194
        if (absres == 12) {
628 adamjking 195
            int temp = nibbleSwap(ensemble[address + 1]); // Retrieve data
213 tk 196
            temp = (temp & 0xFF00);
197
            ensemble[address] = nibbleSwap(value & 0xFF);
628 adamjking 198
            ensemble[address + 1] = nibbleSwap(temp + ((value & 0xF00) >> 8));
199
            sysexSend(address, ((temp << 4) + (value & 0xFFF)), 2);
213 tk 200
        }
628 adamjking 201
 
213 tk 202
        // 16 bit values
203
        if (absres == 16) {
204
            ensemble[address] = nibbleSwap(value & 0xFF);
628 adamjking 205
            ensemble[address + 1] = nibbleSwap((value & 0xFF00) >> 8);
213 tk 206
            sysexSend(address, (value & 0xFFFF), 2);
207
        }
208
    }
628 adamjking 209
 
210
    private static int nibbleSwap(int inInt) {
213 tk 211
        int nibble0 = (((byte) inInt) << 4) & 0xf0;
212
        int nibble1 = (((byte) inInt) >>> 4) & 0x0f;
213
        return (nibble0 | nibble1);
214
    }
628 adamjking 215
 
213 tk 216
    public void sysexSend(int addr, int value, int bytes) {
628 adamjking 217
        for (int c = 0; c < cores.length; c++) {
213 tk 218
            if (cores[c]) {
628 adamjking 219
                SysexMessage sysexMessage = new SysexMessage();
213 tk 220
                try {
221
                    String strMessage = SIDSysexInfo.editEsembleParameterSysex;
628 adamjking 222
                    strMessage = strMessage.replace("<device>", "0"
223
                            + Integer.toString(c));
224
                    strMessage = strMessage
225
                            .replace("<address>", calcAddr(addr));
226
                    strMessage = strMessage.replace("<value>", calcValue(value,
227
                            bytes));
228
 
229
                    int nLengthInBytes = strMessage.length() / 2;
230
                    byte[] abMessage = new byte[nLengthInBytes];
231
                    for (int i = 0; i < nLengthInBytes; i++) {
232
                        abMessage[i] = (byte) Integer.parseInt(strMessage
233
                                .substring(i * 2, i * 2 + 2), 16);
213 tk 234
                    }
628 adamjking 235
 
213 tk 236
                    System.out.println(strMessage);
628 adamjking 237
                    sysexMessage.setMessage(abMessage, abMessage.length);
238
                } catch (Exception e) {
213 tk 239
                    System.out.println("exception!");
240
                    System.out.println(e);
241
                }
628 adamjking 242
                receiver.send(sysexMessage, -1);
243
            }
213 tk 244
        }
245
    }
628 adamjking 246
 
213 tk 247
    public void setCores(boolean[] c) {
248
        cores = c;
628 adamjking 249
    }
250
 
213 tk 251
    public Boolean getCore(int i) {
252
        return cores[i];
628 adamjking 253
    }
254
 
213 tk 255
    protected String calcAddr(int addr) {
256
        String str0 = Integer.toHexString(addr & 0x00F);
257
        String str1 = Integer.toHexString((addr & 0x070) >> 4);
258
        String str2 = Integer.toHexString((addr & 0x180) >> 7);
259
        return ("0" + str2 + str1 + str0);
260
    }
628 adamjking 261
 
213 tk 262
    protected String calcValue(int val, int byt) {
263
        String s = "";
628 adamjking 264
        if (byt == 1) {
213 tk 265
            String s0 = "0";
628 adamjking 266
            String s1 = Integer.toHexString(val & 0x0F);
267
            String s2 = Integer.toHexString((val & 0xF0) >> 4);
268
            s = (s0 + s1 + s0 + s2);
269
        } else if (byt == 2) {
213 tk 270
            String s0 = "0";
628 adamjking 271
            String s1 = Integer.toHexString(val & 0x000F);
272
            String s2 = Integer.toHexString((val & 0x00F0) >> 4);
273
            String s3 = Integer.toHexString((val & 0x0F00) >> 8);
274
            String s4 = Integer.toHexString((val & 0xF000) >> 12);
275
            s = (s0 + s1 + s0 + s2 + s0 + s3 + s0 + s4);
213 tk 276
        }
277
        return s;
278
    }
628 adamjking 279
 
213 tk 280
    public void close() {
281
    }
628 adamjking 282
 
213 tk 283
    public Receiver getReceiver() {
284
        return receiver;
285
    }
286
 
287
    public void send(MidiMessage message, long lTimeStamp) {
288
 
289
    }
628 adamjking 290
 
213 tk 291
    public Ensemble clone() {
292
        Ensemble p = new Ensemble(receiver);
293
        p.setEnsemble(ensemble.clone());
628 adamjking 294
        return p;
295
    }
213 tk 296
}