问题
I need to get the tempo value from midi file. I found out, that the set_tempo command has value 0x51, so i have this piece of code:
for (int i = 0; i < tracks[0].size(); i++) {
MidiEvent event = tracks[0].get(i);
MidiMessage message = event.getMessage();
if (message instanceof MetaMessage) {
MetaMessage mm = (MetaMessage) message;
if(mm.getType()==SET_TEMPO){
// now what?
mm.getData();
}
}
}
But the method getData() returns an array of bytes! How can I convert it to normal human form, a.k.a. integer? I have read it is stored in format like this: "tt tt tt", but the whole big/little endian, signed/unsigned, and variable length things make it too confusing.
回答1:
Tempo is a 3-byte big-endian integer and Bits Per Minute is calculated asBPM = 60,000,000 / (tt tt tt)
byte[] data = mm.getData();
int tempo = (data[0] & 0xff) << 16 | (data[1] & 0xff) << 8 | (data[2] & 0xff);
int bpm = 60000000 / tempo;
回答2:
I use:
mpq = ((data[0] & 0x7f) << 14) | ((data[1] & 0x7f) << 7) | (data[2] & 0x7f);
Where mpq
represents microseconds per quarter note or microseconds per beat.
The reasoning for this is that Midi messages only use 7 bits in each byte to represent data. It should also be noted that, in Java
, a byte data type (of which data is an array) is a signed integer and only has room for 7 data bits.
Since making this post I have had the following response from the MIDI Association:
The parameter number (tttttt) is a 24 bit unsigned integer, in big endian format.
"Set tempo" is a meta-event, belonging to the SMF specification. It applies only to Standard MIDI Files, and like the other meta-events are not supposed to be transmitted over the wires on real time. On the other hand, the Data Byte description that is confusing you applies to the over-the-wire protocol.
The original answer to this topic is therefore correct.
来源:https://stackoverflow.com/questions/22798345/how-to-get-integer-value-from-byte-array-returned-by-metamessage-getdata