midis2jam2:2006 3D MIDI可视化工具的重新制作
- Z2_528014了解作者
- 5.5MB文件大小
- zip文件格式
- 0收藏次数
- VIP专享资源类型
- 0下载次数
- 2022-06-09 05:52上传日期
midis2jam2
midis2jam2是MIDIJam的翻版,续集,v2.0等,它是Scott Haag制作的MIDI文件可视化工具,最近一次更新是在2006年。
midis2jam2旨在忠实地重新创建MIDIJam,同时修复错误并完成GM-1实现。
将来的版本可能会添加扩展功能,例如自定义图形,实时MIDI可视化等。
跑步
从源下载并构建。
git clone https://github.com/wyskoj/midis2jam2
gradlew shadowjar
将.jar从build/libs和Midicsv.exe到新文件夹。 然后运行程序。
java -jar midis2jam2.jar your_midi_file.mid
贡献
分叉并发出拉动请求以直接进行更改。 提出一个问题以请求功能并报告错误。
执照
midis2jam2是根据。 资产版权所有:copyright:200

midis2jam2-master.zip
内容介绍
package org.wysko.midis2jam2;
import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture;
import org.jetbrains.annotations.Nullable;
import org.wysko.midis2jam2.instrument.Guitar;
import org.wysko.midis2jam2.instrument.Instrument;
import org.wysko.midis2jam2.instrument.keyed.Keyboard;
import org.wysko.midis2jam2.instrument.monophonic.pipe.Flute;
import org.wysko.midis2jam2.instrument.monophonic.reed.sax.AltoSax;
import org.wysko.midis2jam2.instrument.monophonic.reed.sax.BaritoneSax;
import org.wysko.midis2jam2.instrument.monophonic.reed.sax.TenorSax;
import org.wysko.midis2jam2.instrument.percussive.Percussion;
import org.wysko.midis2jam2.midi.*;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.IntStream;
public class Midis2jam2 extends SimpleApplication implements ActionListener {
static final long LATENCY_FIX = -200;
private static final boolean USE_DEFAULT_SYNTHESIZER = false;
public List<Instrument> instruments = new ArrayList<>();
public MidiFile file;
Sequencer sequencer;
double timeSinceStart;
boolean seqHasRunOnce = false;
public static void main(String[] args) throws Exception {
Midis2jam2 midijam = new Midis2jam2();
File rawFile = new File("testmidi/miss_you.mid");
if (args.length > 0) {
rawFile = new File(args[0]);
}
midijam.file = MidiFile.readMidiFile(rawFile);
// Define settings
AppSettings settings = new AppSettings(true);
settings.setFrameRate(120);
settings.setTitle("midis2jam2");
settings.setFullscreen(false);
settings.setResolution(1024, 768);
midijam.setSettings(settings);
midijam.setShowSettings(false);
midijam.start();
midijam.setPauseOnLostFocus(false);
// Create a sequencer for the sequence
Sequence sequence = MidiSystem.getSequence(rawFile);
MidiDevice.Info[] info = MidiSystem.getMidiDeviceInfo();
MidiDevice device = null;
for (MidiDevice.Info eachInfo : info) {
if (eachInfo.getName().equals("Microsoft GS Wavetable Synth")) {
device = MidiSystem.getMidiDevice(eachInfo);
break;
}
}
midijam.sequencer = MidiSystem.getSequencer(false);
if (device == null || USE_DEFAULT_SYNTHESIZER) {
midijam.sequencer = MidiSystem.getSequencer(true);
} else {
device.open();
midijam.sequencer = MidiSystem.getSequencer(false);
midijam.sequencer.getTransmitter().setReceiver(device.getReceiver());
}
midijam.sequencer.open();
midijam.sequencer.setSequence(sequence);
// Start the song one second from now
new Timer().schedule(new TimerTask() {
@Override
public void run() {
midijam.sequencer.setTempoInBPM((float) midijam.file.firstTempoInBpm());
if (LATENCY_FIX > 0) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
midijam.sequencer.start();
}
}, LATENCY_FIX);
midijam.seqHasRunOnce = true;
midijam.timeSinceStart = 0;
} else {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
midijam.seqHasRunOnce = true;
midijam.timeSinceStart = 0;
}
}, -LATENCY_FIX);
midijam.sequencer.start();
}
}
}, 1500);
}
/**
* Converts an angle expressed in degrees to radians.
*
* @param deg the angle expressed in degrees
* @return the angle expressed in radians
*/
public static float rad(float deg) {
return deg / 180 * FastMath.PI;
}
/**
* Converts an angle expressed in degrees to radians.
*
* @param deg the angle expressed in degrees
* @return the angle expressed in radians
*/
public static float rad(double deg) {
return (float) (deg / 180 * FastMath.PI);
}
@Override
public void simpleUpdate(float tpf) {
super.simpleUpdate(tpf);
if (sequencer == null) return;
if (!sequencer.isRunning() && !seqHasRunOnce)
return;
timeSinceStart += tpf;
// Update animation
for (Instrument instrument : instruments) {
if (instrument != null) // Null if not implemented yet
instrument.tick(timeSinceStart, tpf);
}
}
/**
* Reads the MIDI file and calculates program events, appropriately creating instances of each instrument and
* assigning the correct events to respective instruments.
*/
private void calculateInstruments() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
//noinspection unchecked
ArrayList<MidiChannelSpecificEvent>[] channels = (ArrayList<MidiChannelSpecificEvent>[]) new ArrayList[16];
// Create 16 ArrayLists for each channel
IntStream.range(0, 16).forEach(i -> channels[i] = new ArrayList<>());
// For each track
for (MidiTrack track : file.tracks) {
if (track == null) continue; // Skip non-existent tracks
/* Skip tracks with no note-on events */
boolean aNoteOn = track.events.stream().anyMatch(event -> event instanceof MidiNoteOnEvent);
if (!aNoteOn) continue;
// Add important events
for (MidiEvent event : track.events) {
if (event instanceof MidiChannelSpecificEvent) {
MidiChannelSpecificEvent channelEvent = (MidiChannelSpecificEvent) event;
int channel = channelEvent.channel;
channels[channel].add(channelEvent);
}
}
}
for (ArrayList<MidiChannelSpecificEvent> channelEvent : channels) {
channelEvent.sort(MidiChannelSpecificEvent.COMPARE_BY_TIME);
}
List<Instrument> instruments = new ArrayList<>();
for (int j = 0, channelsLength = channels.length; j < channelsLength; j++) {
ArrayList<MidiChannelSpecificEvent> channel = channels[j];
if (j == 9) { // Percussion channel
Percussion percussion = new Percussion(this, channel);
instruments.add(percussion);
continue;
}
/* Skip channels with no note-on events */
boolean hasANoteOn = channel.stream().anyMatch(e -> e instanceof MidiNoteOnEvent);
if (!hasANoteOn) continue;
List<MidiProgramEvent> programEvents = new ArrayList<>();
for (MidiChannelSpecificEvent channelEvent : channel) {
if (channelEvent instanceof MidiProgramEvent) {
programEvents.add(((MidiProgramEvent) channelEvent));
}
}
if (programEvents.isEmpty()) { // It is possible for no program event, revert to instrument 0
programEvents.add(new MidiProgramEvent(0, j, 0));
}
int dupC = 0;
// Remove duplicate events (either at duplicate time or same program number)
while (programEvents.size() > 1 &&
(programEvents.get(dupC + 1).time == programEvents.get(dupC).time ||
programEvents.get(dupC + 1).programNum == programEvents.get(dupC).programNum)
) {
programEvents.remove(dupC);
}
if (programEvents.size() == 1) {
instruments.add(fromEvents(programEvents.get(0), channel));
} else {
for (int i = 0; i < programEvents.size() - 1; i++) {
List<MidiChannelSpecificEvent> events = new ArrayList<>();
for (MidiChannelSpecificEvent eventInChannel : channel) {
if (eventInChannel.time < programEvents.get(i + 1).time) {
events.add(eventInChannel);
} else {
break;
}
}
instruments.add(fromEvents(programEvents.get(i), events));
}
List<MidiChannelSpecificEvent> lastInstrumentEvents = new ArrayList<>();
MidiProgramEvent lastProgramEvent = programEvents.get(programEvents.size() - 1);
for (MidiChannelSpecificEvent channelEvent : channel) {
if (channelEv
评论



相关推荐
- gradle-github-actions-plugin:用于Github Actions的Gradle插件gradle-github-actions-plugin:用于Github Actions的Gradle插件
- atlas-github:Gradle插件,将工件发布到githubatlas-github:Gradle插件,将工件发布到github
- github-actions-gradlegithub-actions-gradle
- gradle:gradle中文文档本文档前11章来自github但是比较残缺部分章节无线学院补充翻译、12章-31张来自,感谢他们对Gradle中文社区的支持,31章后为Gradle中文社区无线学院翻译,如有疑义前31章可以联系我们可以随时下架。 每天为开源社区...
- android-gradle-action:使用GitHub操作运行Android Gradle任务android-gradle-action:使用GitHub操作运行Android Gradle任务
- gradle-github-info-plugin:Gradle Github信息插件gradle-github-info-plugin:Gradle Github信息插件
- gradle_githubactions:gradle CI工作流程gradle_githubactions
- gradle-command-action:执行Gradle命令Github操作在GitHub Actions工作流程中执行Gradle命令 该GitHub Action可用于在GitHub Actions支持的任何平台上运行任意Gradle命令。 您可能也对相关的感兴趣,该使您的构建可以轻松获取GitHub Actions环境并相应地标记Gradle...
- github-release-gradle-plugin:一个Gradle插件,用于向Github发送发布github-release-gradle-plugin:一个Gradle插件,用于向Github发送发布
最新资源