MIDI тик в миллисекунду?

Я понимаю, что здесь есть много вопросов, касающихся преобразования тактов MIDI в миллисекунды (например: Как преобразовать временную шкалу midi в фактическую временную шкалу, которую следует воспроизвести, Midi Ticks to Actual PlayBack Seconds !!! (Midi Music), Midi timestamp в секундах), и я просмотрел их все, попытался реализовать предложения, но до сих пор не понял.

(Я упоминал, что я немного «математический фоб»)

Может ли кто-нибудь помочь мне работать на практическом примере? Я использую библиотеку Bass от un4seen. У меня есть все данные, которые мне нужны, просто я не доверяю своим расчетам.

Методы баса

Отметьте

// position of midi stream
uint64_t tick = BASS_ChannelGetPosition(midiFileStream, BASS_POS_MIDI_TICK)

PPQN

//The Pulses Per Quarter Note (or ticks per beat) value of a MIDI stream.
float ppqn;
BASS_ChannelGetAttribute(handle, BASS_ATTRIB_MIDI_PPQN, &ppqn);

Темп

 //tempo in microseconds per quarter note.
 uint32_t tempo = BASS_MIDI_StreamGetEvent( midiFileStream, -1, MIDI_EVENT_TEMPO);

Моя попытка рассчитать значение MS для тика:

float currentMilliseconds = tick * tempo / (ppqn * 1000);

Полученное значение кажется правильным, но я не уверен в нем, так как не совсем понимаю формулу.

printf("tick %llu\n",tick);
printf("ppqn %f\n",ppqn);
printf("tempo %u\n",tempo);
printf("currentMilliseconds %f \n", currentMilliseconds);

Пример вывода:

tick 479
ppqn 24.000000
tempo 599999
currentMilliseconds 11974.980469 

Обновить

Мое замешательство продолжается, но на основе этого сообщение в блоге Я думаю, что у меня правильный код - по крайней мере, вывод кажется точным. И наоборот, ответ, предоставленный @Strikeskids ниже, дает разные результаты. Может быть, у меня там проблема с порядком операций?

float kMillisecondsPerQuarterNote = tempo / 1000.0f;
float kMillisecondsPerTick = kMillisecondsPerQuarterNote / ppqn;
float deltaTimeInMilliseconds = tick * kMillisecondsPerTick;
printf("deltaTimeInMilliseconds %f \n", deltaTimeInMilliseconds);

.

float currentMillis = tick * 60000.0f / ppqn / tempo;
printf("currentMillis %f \n", currentMillis);

Вывод:

 deltaTimeInMilliseconds 11049.982422 
 currentMillis 1.841670 

person spring    schedule 12.07.2014    source источник
comment
Вы знаете, что темп может измениться в середине файла? Вы не можете избежать использования еще большего количества математики.   -  person CL.    schedule 13.07.2014
comment
У вас уже есть микросекунды на четвертную ноту, предоставленные BASS. Разве это не то, что вы сказали, что ищете?   -  person Brad    schedule 13.07.2014
comment
@Brad - нет, я пытаюсь рассчитать миллисекунды для определенных тиков   -  person spring    schedule 13.07.2014


Ответы (2)


Темп указывается в ударах в минуту. Поскольку вы хотите получить время, оно должно быть в знаменателе дроби.

currentTime = currentTick * (beats / tick) * (minutes / beat) * (millis / minute)

millis = tick * (1/ppqn) * (1/tempo) * (1000*60)

эффективно использовать целочисленную арифметику do

currentMillis = tick * 60000 / ppqn / tempo

person Strikeskids    schedule 12.07.2014
comment
Извините, я все еще не понимаю. Если бы вы могли, вы бы отредактировали свой ответ, используя вары, которые я разместил в своем вопросе? Наблюдение за конкретными используемыми переменными поможет мне понять формулу, которую вы описали выше, и то, как она применяется. (добро пожаловать в мой тупой мир... ;-) - person spring; 13.07.2014
comment
Первая линия теоретическая. Вторая строка — это теоретическая версия, преобразованная в ваши переменные, а в третьей строке переменные переупорядочены в формат, который вы бы написали в коде. - person Strikeskids; 14.07.2014
comment
Спасибо. Я обновил свой вопрос с помощью метода и вывода из вашего примера, кода и объяснения, которые я нашел на этом сайте (lastrayofhope.co.uk/2009/12/23/midi-delta-time-ticks-to-seconds/) . Результат двух методов сильно отличается, и я не понимаю, почему. Порядок действий? - person spring; 14.07.2014

Это работает:

float kMillisecondsPerQuarterNote = tempo / 1000.0f;
float kMillisecondsPerTick = kMillisecondsPerQuarterNote / ppqn;
float deltaTimeInMilliseconds = tick * kMillisecondsPerTick;
printf("deltaTimeInMilliseconds %f \n", deltaTimeInMilliseconds);
person spring    schedule 23.07.2014
comment
Я использую формат MIDICSV, и это сработало для меня. currentMs = темп/1000.0f/PPQ * currentClock; - person Totomobile; 11.10.2015