blob: fbbe2184ecf7a2be9ffdff25cdff5d83f89b80af [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.components.midi.xmidi;
/**
* The MIDI file parsing parts of this class are based on code from the XMidi project, written
* by Peter Arthur Loeb (http://www.palserv.com/XMidi/) and used with permission.
* The warranty disclaimer of the MIT license (http://www.opensource.org/licenses/mit-license.html)
* applies to Peter Arthur Loeb's code.
*
* @author <a href="mailto:mark.leicester@energyintellect.com">Mark Leicester</a>
* @author <a href="mailto:peter@palserv.com">Peter Loeb</a>
*/
import org.apache.cocoon.ProcessingException;
public final class Utils
{
public static final String VERSION = "1.2";
/**
convert hex string to byte array
*/
static public byte[] hexToBa(String h, int len) throws ProcessingException
{
int l = h.length();
int cnt = 0;
int bs = 0;
int bc = 0;
byte[] ba = new byte[len];
for (int i = 0; i < l; i++)
{
String s = h.substring(i, i + 1);
int x = " \n\t\r".indexOf(s);
if (x != -1)
{
continue;
}
int tmp = "0123456789ABCDEF".indexOf(s.toUpperCase());
if (bc == 0)
{
bs = tmp;
}
else
if (bc == 1)
{
bs <<= 4;
bs |= tmp;
}
else
{
throw new ProcessingException("hexToBa: internal error");
}
bc++;
if (bc >= 2)
{
ba[cnt] = (byte) bs;
cnt++;
bc = 0;
}
}
if (bc != 0)
{
throw new ProcessingException("un-even number of hex digits");
}
if (cnt != len)
{
throw new ProcessingException(
"hexToBa: count (" + cnt + ") != length (" + len + ")");
}
return ba;
}
/**
convert byte array to string (not hex)
*/
public static String baToString(byte[] b, int strt, int end)
{
int l = end - strt + 1;
char[] c = new char[l];
for (int j = 0; j < l; j++)
{
c[j] = (char) b[j];
}
return new String(c);
}
/**
convert byte array to hex string
*/
public static String baToHex(byte[] b, int strt, int end)
throws ProcessingException
{
int l = end - strt + 1;
if (b.length < end)
{
throw new ProcessingException(
"baToHex: length error; b.length="
+ b.length
+ ", strt="
+ strt
+ ", end="
+ end
+ ", l="
+ l);
}
StringBuffer sb = new StringBuffer("");
for (int i = 0; i < l; i++)
{
int t = getUnsignedByte(b[strt + i]);
int a = t / 16;
int aa = t % 16;
sb.append("0123456789ABCDEF".substring(a, a + 1));
sb.append("0123456789ABCDEF".substring(aa, aa + 1));
}
return sb.toString();
}
/**
convert int to byte array of length c
*/
static public byte[] intToBa(int n, int c) throws ProcessingException
{
byte[] b = new byte[c];
int t = n;
for (int i = 0; i < c; i++)
{
int j = c - i - 1;
int k = t % 256;
b[j] = (byte) k;
t /= 256;
}
if (t > 0)
{
throw new ProcessingException(
"intToBa: t is " + t + ", n = " + n + ", c = " + c);
}
return b;
}
/**
convert byte array to int
*/
static public int baToInt(byte[] b, int strt, int end)
throws ProcessingException
{
if (end > b.length - 1)
{
throw new ProcessingException(
"baToInt: strt = "
+ strt
+ ", end = "
+ end
+ ", b.length = "
+ b.length);
}
int l = end - strt + 1;
int i = 0;
for (int j = 0; j < l; j++)
{
int p = strt + l - j - 1;
// get int value of unsigned byte into k
if (p > b.length - 1)
{
throw new ProcessingException(
"baToInt: p = "
+ p
+ ", strt = "
+ strt
+ ", end = "
+ end
+ ", l = "
+ l
+ ", j = "
+ j
+ ", i = "
+ i);
}
int k = getUnsignedByte(b[p]);
int n = pow(256, j);
i += n * k;
}
return i;
}
/**
convert byte (unsigned) to int
*/
static public int getUnsignedByte(byte b)
{
int t = 0;
if ((b & 128) == 128)
{
t = 1;
}
b &= 127;
int k = b;
k += t * 128;
return k;
}
/**
convert delta time to byte array
a delta time is expressed as a
byte array, length unknown (4 or less)
*/
static public ByteLen deltaToInt(byte[] b, int offset)
throws ProcessingException
{
/*
- capture up to four bytes including first with hi-ord
bit off
- turn off hi-ord bits
- accumulate 4 groups of 7 into 28 bit number with
hi-ord 4 bits zero.
*/
int j = 0;
byte[] ba = new byte[4];
boolean jFlag = true;
while (jFlag)
{
if ((j + offset) > b.length)
{
throw new ProcessingException(
"deltaToInt: length error; j = "
+ j
+ ", offset = "
+ offset
+ ", b.length = "
+ b.length);
}
ba[j] = b[j + offset];
if (ba[j] >= 0)
{
jFlag = false;
}
else
{
ba[j] &= 127;
}
/*this.getLogger().debug(
"deltaToInt: j = " + j + ", ba = " + baToInt(ba, 0, j));*/
j++;
}
int s = 0;
for (int i = 0; i < j; i++)
{
int k = j - i - 1;
int p = pow(128, i);
int m = ba[k];
s += m * p;
/*this.getLogger().debug(
"deltaToInt: in loop: s = "
+ s
+ ", i = "
+ i
+ ", j = "
+ j
+ ", k = "
+ k
+ ", p = "
+ p
+ ", m = "
+ m);*/
}
/*this.getLogger().debug("deltaToInt: s = " + s);*/
ByteLen bl = new ByteLen(intToBa(s, 4), j);
return bl;
}
/**
compute b to the e power (b ** e)
*/
static public int pow(int b, int e)
{
int a = 1;
for (int i = 0; i < e; i++)
{
a *= b;
}
return a;
}
public static int getPW(byte[] dta, int offset) throws ProcessingException
{
int hi = baToInt(dta, offset, offset);
int lo = baToInt(dta, offset + 1, offset + 1);
hi <<= 7;
lo |= hi;
return lo;
}
public static int getNextHiOrd(byte[] dta, int offset)
throws ProcessingException
{
int ol = 0;
boolean tflag = true;
for (int o = offset + 1; o < dta.length - 1; o++)
{
if (tflag)
{
int x = baToInt(dta, o, o);
if ((x & 128) == 128)
{
tflag = false;
ol = o;
}
}
}
if (tflag)
{
ol = offset + dta.length;
}
return ol;
}
/**
convert byte array to delta time
a delta time is expressed as a
byte array, length unknown (4 or less)
*/
public static byte[] intToDelta(byte[] t) throws ProcessingException
{
/*
from fullword binary value to variable (midi) value:
- split number into 5 bit groups of 4 7 7 7 7
- just deal with the four groups of 7 (ignore the 4)
- put each group of 7 into a byte
- case 1: whole full word is zero.
return one byte of zero.
- case 2: some non-zero bit (after first four bits)
- work from left to right
- throw away bytes which are zero until non-zero byte
encountered
- turn on hi-ord bit on all but last byte
*/
int i1 = baToInt(t, 0, t.length - 1);
//this.getLogger().debug("intToDelta: i1 = " + i1 + ", t = " + XMidiUtils.baToHex(t, 0, t.length - 1));
if (i1 == 0)
{
byte[] b = new byte[1];
b[0] = 0;
return b;
}
int i2 = i1;
byte[] b1 = new byte[4];
for (int i = 0; i < 4; i++)
{
int j = 4 - i - 1;
int k = i2 % 128;
i2 /= 128;
b1[j] = (byte) k;
}
int j = -1;
boolean bFlag = false;
for (int i = 0; i < 4; i++)
{
if (bFlag)
{
continue;
}
if (b1[i] != 0)
{
j = i;
bFlag = true;
}
}
int k = 4 - j;
byte[] b2 = new byte[k];
for (int i = 0; i < k; i++)
{
b2[i] = b1[i + j];
if (i != (k - 1))
{
b2[i] |= 128;
}
}
return b2;
}
public static int stringToInt(String s)
{
Integer i = new Integer(s);
int r = i.intValue();
return r;
}
}