/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
// TODO:
// - define and use a global symbolic constant for 60000000 (see convertTempo)
/**
* Some utilities for MIDI (some stuff is used from javax.sound.midi)
*
* @author Florian Bomers
*/
public final class MidiUtils {
/**
* Suppresses default constructor, ensuring non-instantiability.
*/
private MidiUtils() {
}
/** return true if the passed message is Meta End Of Track */
// first check if it is a META message at all
return false;
}
// now get message and check for end of track
}
/** return if the given message is a meta tempo message */
// first check if it is a META message at all
return false;
}
// now get message and check for tempo
// meta type must be 0x51, and data length must be 3
}
/** parses this message for a META tempo message and returns
* the tempo in MPQ, or -1 if this isn't a tempo message
*/
// first check if it is a META message at all
return -1;
}
return -1;
}
return tempo;
}
/**
* converts<br>
* 1 - MPQ-Tempo to BPM tempo<br>
* 2 - BPM tempo to MPQ tempo<br>
*/
if (tempo <= 0) {
tempo = 1;
}
return ((double) 60000000l) / tempo;
}
/**
* convert tick to microsecond with given tempo.
* Does not take tempo changes into account.
* Does not work for SMPTE timing!
*/
}
/**
* convert tempo to microsecond with given tempo
* Does not take tempo changes into account.
* Does not work for SMPTE timing!
*/
// do not round to nearest tick
//return (long) Math.round((((double)us) * resolution) / tempoMPQ);
}
/**
* Given a tick, convert to microsecond
* @param cache tempo info and current tempo
*/
return (long) (1000000 * seconds);
}
}
// optimization to not always go through entire list of tempo events
// walk through all tempo changes and add time for the respective blocks
if (snapshotIndex <= 0
|| snapshotIndex >= cacheCount
snapshotMicro = 0;
snapshotIndex = 0;
}
if (cacheCount > 0) {
// this implementation needs a tempo event at tick 0!
int i = snapshotIndex + 1;
snapshotIndex = i;
i++;
}
}
return us;
}
/**
* Given a microsecond time, convert to tick.
* returns tempo at the given time in cache.getCurrTempoMPQ
*/
* ((double) seq.getDivisionType())
* ((double) seq.getResolution()))
/ ((double) 1000000);
}
return tick;
}
}
// walk through all tempo changes and add time for the respective blocks
// to find the right tick
// this loop requires that the first tempo Event is at time 0
while (i < cacheCount) {
break;
}
i++;
}
//if (Printer.debug) Printer.debug(" -> convert back = " + (tick2microsecond(seq, tick, null) / 1000)+" microseconds");
}
return tick;
}
/**
* Binary search for the event indexes of the track
*
* @param tick - tick number of index to be found in array
* @return index in track which is on or after "tick".
* if no entries are found that follow after tick, track.size() is returned
*/
int ret = 0;
if (tick > 0) {
int low = 0;
// take the middle event as estimate
// tick of estimate
if (t == tick) {
break;
} else if (t < tick) {
// estimate too low
// "or after tick"
ret++;
break;
}
} else { // if (t>tick)
// estimate too high
}
}
}
return ret;
}
public static final class TempoCache {
long[] ticks;
// microsecond at the snapshot
private boolean firstTempoIsFake = false;
public TempoCache() {
// just some defaults, to prevents weird stuff
ticks = new long[1];
tempos = new int[1];
snapshotIndex = 0;
snapshotMicro = 0;
}
this();
}
// tempo events only occur in track 0
for (int i = 0; i < c; i++) {
if (isMetaTempo(msg)) {
// found a tempo event. Add it to the list
}
}
}
firstTempoIsFake = true;
if ((size > 1)
// do not need to add an initial tempo event at the beginning
size--;
firstTempoIsFake = false;
}
int e = 0;
if (firstTempoIsFake) {
// add tempo 120 at beginning
e++;
}
}
snapshotIndex = 0;
snapshotMicro = 0;
}
public int getCurrTempoMPQ() {
return currTempo;
}
}
if (i > 0) i--;
return startTempoMPQ;
}
return (float) tempos[i];
}
}
}
}
}