Я уже давно играюсь с JFugue 5.0.9. Пока я использую метод Player.play (Pattern), кажется, что все работает нормально.
Но как только я использую Sequence, попробуйте отправить его на внешнее миди-устройствовремя музыки совершенно неправильное и ненадежное.
Я работал с этим миди-устройством через обычное программное обеспечение для секвенирования без каких-либо проблем, но, похоже, он не работает, когда я использую библиотеку JFugue.
Даже что-то простое, как показано на рисунке ниже, не работает правильно. Первые две ноты почти играются вместе (между ними есть небольшая задержка), а последняя нота вообще не воспроизводится.
private final Predicate<MidiDevice.Info> isGrandPiano() {
return deviceInfo ->
deviceInfo.getName().toLowerCase().contains("portable grand") &&
deviceInfo.getDescription().toLowerCase().contains("external midi");
}
public void playSongOnDevice() {
Info deviceInfo = Arrays.stream(MidiSystem.getMidiDeviceInfo())
.filter(isGrandPiano())
.findFirst()
.orElse(null);
try {
MusicReceiver receiver = new MusicReceiver(MidiSystem.getMidiDevice(deviceInfo));
receiver.sendSequence(player.getSequence(new Pattern("V0 T60 Dq Eq Fq Gq Dq Eq Fq Gq Dq Eq Fq Gq")));
} catch (MidiUnavailableException e) {
e.printStackTrace();
throw new IllegalArgumentException(e);
}
}
Я не вижу, что еще я мог бы сделать, чтобы исправить это,Это даже идет более неправильно, когда я устанавливаю метроном в фоновом режиме с V9. Поэтому я подумал о том, чтобы сделать это как можно более простым.
Хорошая новость заключается в том, что внешнее миди-устройство реагирует (Yamaha DGX-660), плохая новость в том, что он вообще не учитывает времяи, кажется, иногда пропускает заметки. Я играл в тьюринг вкл / выкл местного времени или внешней синхронизации, но никаких изменений в поведении. Я обновил до последней и самой лучшей версии Java 8 и yamaha , но ничего не помогает.
Что мне здесь не хватает? Кстати, также используя Windows 10 .
С уважением,
РЕДАКТИРОВАТЬ: Одно дополнение к этому. Я также тестировал с той же самой последовательностью для игрока, так как она также принимает последовательность. Когда я передаю ту же самую последовательность в Player.play, это работает нормально.
Разница в том, что для receive.sendSequence вы передаете некоторый метод, подобный этому извлечению из org.jfugue.midi.MidiToolsкласс:
public static void sendSortedMidiMessagesToReceiver(Map<Long, List<MidiMessage>> sortedMidiMessages, float sequenceDivisionType, int sequenceResolution, Receiver receiver) {
int bpm = MidiDefaults.DEFAULT_TEMPO_BEATS_PER_MINUTE;
int ticksPerSecond;
long prevTick = 0L;
long msTime = 0L;
long largestTick = getLargestKey(sortedMidiMessages);
if (sequenceDivisionType == Sequence.PPQ) {
ticksPerSecond = (int)(sequenceResolution * bpm / 60.0D);
} else {
double framesPerSecond =
(sequenceDivisionType == Sequence.SMPTE_24 ? 24
: (sequenceDivisionType == Sequence.SMPTE_25 ? 25
: (sequenceDivisionType == Sequence.SMPTE_30 ? 30
: (sequenceDivisionType == Sequence.SMPTE_30DROP ? 29.97 : 24))));
ticksPerSecond = (int)(sequenceResolution * framesPerSecond);
}
for (long tick = 0; tick <= largestTick; tick++) {
if (sortedMidiMessages.containsKey(tick)) {
msTime = calculateTime(tick - prevTick, ticksPerSecond);
List<MidiMessage> messages = sortedMidiMessages.get(tick);
for (MidiMessage message : messages) {
if ((message instanceof MetaMessage) && (sequenceDivisionType == Sequence.PPQ) && (((MetaMessage)message).getType() == MidiDefaults.SET_TEMPO_MESSAGE_TYPE)) {
ticksPerSecond = calculateTicksPerSecondFromMidiSetTempoMessageData(((MetaMessage)message).getData(), sequenceResolution);
msTime = calculateTime(tick - prevTick, ticksPerSecond);
} else {
receiver.send(message, msTime);
}
}
try {
Thread.sleep(msTime);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
prevTick = tick;
}
}
}
Я специально добавил точку останова на строку
...
} else {
receiver.send(message, msTime);
}
...
, потому что Thread.sleep (msTime) привлек мое внимание. Я видел эти результаты в последовательности, упомянутой выше:
<code><pre>
msTime message
0 [-112, 62, 64]
2000 [-128, 62, 64]
2000 [-112, 64, 64]
2000 [-128, 64, 64]
2000 [-112, 65, 64]
2000 [-128, 65, 64]
2000 [-112, 67, 64]
2000 [-128, 67, 64]
2000 [-112, 62, 64]
2000 [-128, 62, 64]
2000 [-112, 64, 64]
2000 [-128, 64, 64]
2000 [-112, 65, 64]
2000 [-128, 65, 64]
2000 [-112, 67, 64]
2000 [-128, 67, 64]
2000 [-112, 62, 64]
2000 [-128, 62, 64]
2000 [-112, 64, 64]
2000 [-128, 64, 64]
2000 [-112, 65, 64]
2000 [-128, 65, 64]
2000 [-112, 67, 64]
2000 [-128, 67, 64]
2000 [-1, 47, 0]
Я не эксперт по миди, но я нахожу это немного странным в первой ноте, у меня msTime в0, что на 2000 для всех остальных. Это может объяснить, почему первые заметки склеены. Я не уверен ...
EDIT2: Использование MidiMapper (я использовал Coolsoft MidiMapper) имеет те же результаты для Microsoft Wavetable Synth. У него точно такая же проблема, поэтому я не думаю, что это связано с моим Piano, так как это внутреннее устройство Windows Midi. Но, как объяснено, это вызвано методом receive.sendSequence. У кого-нибудь есть такие же проблемы с этой версией JFugue 5.0.9?