001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.midi.xmidi;
018:
019: /**
020: * The MIDI file parsing parts of this class are based on code from the XMidi project, written
021: * by Peter Arthur Loeb (http://www.palserv.com/XMidi/) and used with permission.
022: * The warranty disclaimer of the MIT license (http://www.opensource.org/licenses/mit-license.html)
023: * applies to Peter Arthur Loeb's code.
024: *
025: * @author <a href="mailto:mark.leicester@energyintellect.com">Mark Leicester</a>
026: * @author <a href="mailto:peter@palserv.com">Peter Loeb</a>
027: */
028:
029: import org.apache.cocoon.ProcessingException;
030:
031: public final class Utils {
032: public static final String VERSION = "1.2";
033:
034: /**
035: convert hex string to byte array
036: */
037: static public byte[] hexToBa(String h, int len)
038: throws ProcessingException {
039: int l = h.length();
040: int cnt = 0;
041: int bs = 0;
042: int bc = 0;
043: byte[] ba = new byte[len];
044: for (int i = 0; i < l; i++) {
045: String s = h.substring(i, i + 1);
046: int x = " \n\t\r".indexOf(s);
047: if (x != -1) {
048: continue;
049: }
050: int tmp = "0123456789ABCDEF".indexOf(s.toUpperCase());
051: if (bc == 0) {
052: bs = tmp;
053: } else if (bc == 1) {
054: bs <<= 4;
055: bs |= tmp;
056: } else {
057: throw new ProcessingException("hexToBa: internal error");
058: }
059: bc++;
060: if (bc >= 2) {
061: ba[cnt] = (byte) bs;
062: cnt++;
063: bc = 0;
064: }
065: }
066: if (bc != 0) {
067: throw new ProcessingException(
068: "un-even number of hex digits");
069: }
070: if (cnt != len) {
071: throw new ProcessingException("hexToBa: count (" + cnt
072: + ") != length (" + len + ")");
073: }
074: return ba;
075: }
076:
077: /**
078: convert byte array to string (not hex)
079: */
080: public static String baToString(byte[] b, int strt, int end) {
081: int l = end - strt + 1;
082: char[] c = new char[l];
083: for (int j = 0; j < l; j++) {
084: c[j] = (char) b[j];
085: }
086: return new String(c);
087: }
088:
089: /**
090: convert byte array to hex string
091: */
092: public static String baToHex(byte[] b, int strt, int end)
093: throws ProcessingException {
094: int l = end - strt + 1;
095: if (b.length < end) {
096: throw new ProcessingException(
097: "baToHex: length error; b.length=" + b.length
098: + ", strt=" + strt + ", end=" + end
099: + ", l=" + l);
100: }
101: StringBuffer sb = new StringBuffer("");
102: for (int i = 0; i < l; i++) {
103: int t = getUnsignedByte(b[strt + i]);
104: int a = t / 16;
105: int aa = t % 16;
106: sb.append("0123456789ABCDEF".substring(a, a + 1));
107: sb.append("0123456789ABCDEF".substring(aa, aa + 1));
108: }
109: return sb.toString();
110: }
111:
112: /**
113: convert int to byte array of length c
114: */
115: static public byte[] intToBa(int n, int c)
116: throws ProcessingException {
117: byte[] b = new byte[c];
118: int t = n;
119: for (int i = 0; i < c; i++) {
120: int j = c - i - 1;
121: int k = t % 256;
122: b[j] = (byte) k;
123: t /= 256;
124: }
125: if (t > 0) {
126: throw new ProcessingException("intToBa: t is " + t
127: + ", n = " + n + ", c = " + c);
128: }
129: return b;
130: }
131:
132: /**
133: convert byte array to int
134: */
135: static public int baToInt(byte[] b, int strt, int end)
136: throws ProcessingException {
137: if (end > b.length - 1) {
138: throw new ProcessingException("baToInt: strt = " + strt
139: + ", end = " + end + ", b.length = " + b.length);
140: }
141: int l = end - strt + 1;
142: int i = 0;
143: for (int j = 0; j < l; j++) {
144: int p = strt + l - j - 1;
145: // get int value of unsigned byte into k
146: if (p > b.length - 1) {
147: throw new ProcessingException("baToInt: p = " + p
148: + ", strt = " + strt + ", end = " + end
149: + ", l = " + l + ", j = " + j + ", i = " + i);
150: }
151: int k = getUnsignedByte(b[p]);
152: int n = pow(256, j);
153: i += n * k;
154: }
155: return i;
156: }
157:
158: /**
159: convert byte (unsigned) to int
160: */
161: static public int getUnsignedByte(byte b) {
162: int t = 0;
163: if ((b & 128) == 128) {
164: t = 1;
165: }
166: b &= 127;
167: int k = b;
168: k += t * 128;
169: return k;
170: }
171:
172: /**
173: convert delta time to byte array
174: a delta time is expressed as a
175: byte array, length unknown (4 or less)
176: */
177: static public ByteLen deltaToInt(byte[] b, int offset)
178: throws ProcessingException {
179: /*
180: - capture up to four bytes including first with hi-ord
181: bit off
182: - turn off hi-ord bits
183: - accumulate 4 groups of 7 into 28 bit number with
184: hi-ord 4 bits zero.
185: */
186: int j = 0;
187: byte[] ba = new byte[4];
188: boolean jFlag = true;
189: while (jFlag) {
190: if ((j + offset) > b.length) {
191: throw new ProcessingException(
192: "deltaToInt: length error; j = " + j
193: + ", offset = " + offset
194: + ", b.length = " + b.length);
195: }
196: ba[j] = b[j + offset];
197: if (ba[j] >= 0) {
198: jFlag = false;
199: } else {
200: ba[j] &= 127;
201: }
202: /*this.getLogger().debug(
203: "deltaToInt: j = " + j + ", ba = " + baToInt(ba, 0, j));*/
204: j++;
205: }
206: int s = 0;
207: for (int i = 0; i < j; i++) {
208: int k = j - i - 1;
209: int p = pow(128, i);
210: int m = ba[k];
211: s += m * p;
212: /*this.getLogger().debug(
213: "deltaToInt: in loop: s = "
214: + s
215: + ", i = "
216: + i
217: + ", j = "
218: + j
219: + ", k = "
220: + k
221: + ", p = "
222: + p
223: + ", m = "
224: + m);*/
225: }
226: /*this.getLogger().debug("deltaToInt: s = " + s);*/
227: ByteLen bl = new ByteLen(intToBa(s, 4), j);
228: return bl;
229: }
230:
231: /**
232: compute b to the e power (b ** e)
233: */
234: static public int pow(int b, int e) {
235: int a = 1;
236: for (int i = 0; i < e; i++) {
237: a *= b;
238: }
239: return a;
240: }
241:
242: public static int getPW(byte[] dta, int offset)
243: throws ProcessingException {
244: int hi = baToInt(dta, offset, offset);
245: int lo = baToInt(dta, offset + 1, offset + 1);
246: hi <<= 7;
247: lo |= hi;
248: return lo;
249: }
250:
251: public static int getNextHiOrd(byte[] dta, int offset)
252: throws ProcessingException {
253: int ol = 0;
254: boolean tflag = true;
255: for (int o = offset + 1; o < dta.length - 1; o++) {
256: if (tflag) {
257: int x = baToInt(dta, o, o);
258: if ((x & 128) == 128) {
259: tflag = false;
260: ol = o;
261: }
262: }
263: }
264: if (tflag) {
265: ol = offset + dta.length;
266: }
267: return ol;
268: }
269:
270: /**
271: convert byte array to delta time
272: a delta time is expressed as a
273: byte array, length unknown (4 or less)
274: */
275: public static byte[] intToDelta(byte[] t)
276: throws ProcessingException {
277: /*
278: from fullword binary value to variable (midi) value:
279: - split number into 5 bit groups of 4 7 7 7 7
280: - just deal with the four groups of 7 (ignore the 4)
281: - put each group of 7 into a byte
282: - case 1: whole full word is zero.
283: return one byte of zero.
284: - case 2: some non-zero bit (after first four bits)
285: - work from left to right
286: - throw away bytes which are zero until non-zero byte
287: encountered
288: - turn on hi-ord bit on all but last byte
289: */
290: int i1 = baToInt(t, 0, t.length - 1);
291: //this.getLogger().debug("intToDelta: i1 = " + i1 + ", t = " + XMidiUtils.baToHex(t, 0, t.length - 1));
292: if (i1 == 0) {
293: byte[] b = new byte[1];
294: b[0] = 0;
295: return b;
296: }
297: int i2 = i1;
298: byte[] b1 = new byte[4];
299: for (int i = 0; i < 4; i++) {
300: int j = 4 - i - 1;
301: int k = i2 % 128;
302: i2 /= 128;
303: b1[j] = (byte) k;
304: }
305: int j = -1;
306: boolean bFlag = false;
307: for (int i = 0; i < 4; i++) {
308: if (bFlag) {
309: continue;
310: }
311: if (b1[i] != 0) {
312: j = i;
313: bFlag = true;
314: }
315: }
316: int k = 4 - j;
317: byte[] b2 = new byte[k];
318: for (int i = 0; i < k; i++) {
319: b2[i] = b1[i + j];
320: if (i != (k - 1)) {
321: b2[i] |= 128;
322: }
323: }
324: return b2;
325: }
326:
327: public static int stringToInt(String s) {
328: Integer i = new Integer(s);
329: int r = i.intValue();
330: return r;
331: }
332:
333: }
|