Как получить целочисленное значение из массива байтов, возвращаемого MetaMessage.getData()?

Мне нужно получить значение темпа из файла midi. Я узнал, что команда set_tempo имеет значение 0x51, поэтому у меня есть этот фрагмент кода:

    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();
            }
        }
    }

Но метод getData() возвращает массив байтов! Как я могу преобразовать его в обычную человеческую форму, также известную как целое число? Я читал, что он хранится в таком формате: «tt tt tt», но все вещи с обратным/обратным порядком байтов, со знаком/без знака и с переменной длиной делают его слишком запутанным.


person Leprechaun    schedule 01.04.2014    source источник


Ответы (2)


Темп представляет собой 3-байтовое целое число с обратным порядком байтов, а бит в минуту рассчитывается как
BPM = 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;
person apangin    schedule 01.04.2014

Я использую:

mpq = ((data[0] & 0x7f) << 14) | ((data[1] & 0x7f) << 7) | (data[2] & 0x7f);

Где mpq представляет микросекунды на четвертную ноту или микросекунды на долю.

Причина этого в том, что сообщения Midi используют только 7 бит в каждом байте для представления данных. Следует также отметить, что в Java тип данных byte (данные которого представляют собой массив) представляет собой целое число со знаком и имеет место только для 7 битов данных.

После написания этого поста я получил следующий ответ от MIDI Association:

Номер параметра (tttttt) представляет собой 24-битное целое число без знака в формате с обратным порядком байтов.

«Установить темп» — это мета-событие, относящееся к спецификации SMF. Он применяется только к стандартным MIDI-файлам и, как и другие мета-события, не должен передаваться по проводам в режиме реального времени. С другой стороны, описание байта данных, которое сбивает вас с толку, относится к протоколу беспроводной связи.

Поэтому исходный ответ на эту тему правильный.

person user8182116    schedule 08.08.2017
comment
Разве оба решения не дают одинаковых результатов? Если это так, то я не понимаю, в чем преимущество вашего решения. - person Leprechaun; 09.08.2017
comment
Результаты будут отличаться примерно в 4 раза. Даже если первый результат разделить на 4, он будет отличаться от второго результата до 3% в зависимости от последовательности битов и наличия знакового бита в каждом элементе данных. Способ проверить это — проверить продолжительность музыкального произведения, воспроизводимого или записанного в различных темпах. - person user8182116; 09.08.2017
comment
Это странно. Я действительно использовал принятый ответ в своей бакалаврской диссертации несколько лет назад. Это дало правильные результаты при печати и оценке некоторых миди-данных, коррелирующих с предполагаемыми фундаментальными показателями. И длины записей также были равны построенным и оцененным миди-сигналам. Треки были длиной до нескольких минут, так что разница в 4 раза будет заметна сразу. Если то, что вы говорите, правда, единственный способ, которым я могу это объяснить, это то, что это можно наблюдать только при определенных значениях темпа. Это правильно? - person Leprechaun; 09.08.2017
comment
Расхождение может варьироваться от 0 до примерно 3% в зависимости от темпа. Вы можете понять это, если посмотрите на битовый рисунок. Темп 120 ударов в минуту соответствует mpq 500000. В двоичном виде это - person user8182116; 10.08.2017
comment
Расхождение может варьироваться от 0 до примерно 3% в зависимости от темпа. Вы можете понять это, если посмотрите на битовый рисунок. Темп 120 ударов в минуту представляет собой mpq 500000. Это в двоичном виде равно 001111010000100100000. Если вы разделите это на три группы по семь бит и преобразуете в десятичное число, вы получите 30 66 32. Если у вас есть этот темп в вашей программе и вы делаете System.out .println (данные [0] + + данные [1] + + данные [2]); вы получите 30 66 32. Я не могу найти ничего в спецификации Midi, в которой говорится, что двоичные переменные должны быть подписаны или не подписаны, но похоже, что Java использует подписанные переменные. - person user8182116; 10.08.2017
comment
Я займусь этим, когда у меня будет свободное время. Если это действительно так, я изменю принятый ответ. - person Leprechaun; 10.08.2017
comment
Я только что получил следующий ответ от Ассоциации MIDI: Номер параметра (tttttt) представляет собой 24-битное целое число без знака в формате с обратным порядком байтов. Set tempo — это мета-событие, относящееся к спецификации SMF. Он применяется только к стандартным MIDI-файлам и, как и другие мета-события, не должен передаваться по проводам в режиме реального времени. С другой стороны, описание байта данных, которое сбивает вас с толку, относится к протоколу беспроводной связи. Принятый ответ на ваш пост является правильным, и я прошу прощения за путаницу, которую я вызвал у вас. - person user8182116; 12.08.2017
comment
О, тогда ок. Тем не менее, если предоставленный вами фрагмент кода верен для аналогичного (по сети) протокола / стандарта, вы можете указать это в своем ответе и оставить его там. Это может быть полезно для других. Тем не менее, спасибо за ваше время и усилия. - person Leprechaun; 12.08.2017