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
评论
    相关推荐