[英]Java midi program selection strange behaviour
我试图找到有关此的任何信息,但找不到任何有帮助的信息。
我正在尝试制作一个程序,该程序生成一个MIDI文件,该文件由使用不同乐器(程序)同时演奏的两个乐器组成。 我一直在使用示例程序: http : //www.cs.cornell.edu/courses/cs211/2008sp/examples/MidiSynth.java.txt作为模板,但是当我尝试人工创建midi事件时(相对于使用示例程序中的合成器即时生成它们),生成的midi文件似乎并不关心我是否切换了程序,对文件中的每个音符使用最后更改为的程序,包括两个midi-轨道,即使我已将程序更改数据保存到两个轨道中。 我已经为我的程序粘贴了代码,因为:
import java.io.File;
import java.io.IOException;
import javax.sound.midi.Sequence;
import javax.sound.midi.Soundbank;
import javax.sound.midi.Sequencer;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.Instrument;
import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;
import javax.sound.midi.InvalidMidiDataException;
public class MidiTest2
{
/* This velocity is used for all notes.
*/
private static final int VELOCITY = 64;
final int PROGRAM = 192;
final int NOTEON = 144;
final int NOTEOFF = 128;
long startTime;
Sequence sequence;
Synthesizer synthesizer;
Sequencer sequencer;
Instrument instruments[];
ChannelData channels[];
ChannelData cc;
//int instrumentCounter = 0;
Track track;
MidiTest2(){
try{
if(synthesizer == null){
if((synthesizer = MidiSystem.getSynthesizer()) == null){
System.out.println("getSynthesizer() failed");
return;
}
}
synthesizer.open();
sequencer = MidiSystem.getSequencer();
sequence = new Sequence(Sequence.PPQ, 10);
}catch(Exception e){
e.printStackTrace();
return;
}
Soundbank sb = synthesizer.getDefaultSoundbank();
if(sb != null){
instruments = synthesizer.getDefaultSoundbank().getInstruments();
synthesizer.loadInstrument(instruments[0]);
}
MidiChannel midiChannels[] = synthesizer.getChannels();
channels = new ChannelData[midiChannels.length];
for(int i = 0; i < channels.length;++i){
channels[i] = new ChannelData(midiChannels[i], i);
}
cc = channels[0];
}
public void createShortEvent(int type, int num){
ShortMessage message = new ShortMessage();
try{
long millis = System.currentTimeMillis() - startTime;
long tick = millis * sequence.getResolution() / 500;
message.setMessage(type+cc.num, num, cc.velocity);
System.out.println("Type: " + message.getCommand() + ", Data1: " + message.getData1() + ", Data2: " + message.getData2() + ", Tick: " + tick);
MidiEvent event = new MidiEvent(message, tick);
track.add(event);
}catch (Exception e){
e.printStackTrace();
}
}
public void createShortEvent(int type, int num, int eventTime){
ShortMessage message = new ShortMessage();
try{
//long millis = System.currentTimeMillis() - startTime;
long tick = eventTime * sequence.getResolution();
message.setMessage(type+cc.num, num, cc.velocity);
System.out.println("Type: " + message.getCommand() + ", Data1: " + message.getData1() + ", Data2: " + message.getData2() + ", Tick: " + tick);
MidiEvent event = new MidiEvent(message, tick);
track.add(event);
}catch (Exception e){
e.printStackTrace();
}
}
public void saveMidiFile(){
try {
int[] fileTypes = MidiSystem.getMidiFileTypes(sequence);
if (fileTypes.length == 0) {
System.out.println("Can't save sequence");
} else {
if (MidiSystem.write(sequence, fileTypes[0], new File("testmidi.mid")) == -1) {
throw new IOException("Problems writing to file");
}
}
} catch (SecurityException ex) {
} catch (Exception ex) {
ex.printStackTrace();
}
}
void run(){
//System.out.println("sequence: " + sequence.getTracks().length);
createNewTrack(0);
createShortEvent(NOTEON, 60, 2);
createShortEvent(NOTEOFF, 60, 3);
createShortEvent(NOTEON, 61, 3);
createShortEvent(NOTEOFF, 61, 4);
createShortEvent(NOTEON, 62, 4);
createShortEvent(NOTEOFF, 62, 5);
createShortEvent(NOTEON, 63, 5);
createShortEvent(NOTEOFF, 63, 6);
createNewTrack(5);
createShortEvent(NOTEON, 50, 1);
createShortEvent(NOTEOFF, 50, 5);
playMidiFile();
saveMidiFile();
}
void printTrack(int num){
Track tempTrack = sequence.getTracks()[num];
System.out.println(tempTrack.get(0).getTick());
}
void playMidiFile(){
try{
sequencer.open();
sequencer.setSequence(sequence);
}catch (Exception e){
e.printStackTrace();
}
sequencer.start();
}
void createNewTrack(int program){
track = sequence.createTrack();
programChange(program);
}
void programChange(int program){
cc.channel.programChange(program);
System.out.println("program: " + program);
startTime = System.currentTimeMillis();
createShortEvent(PROGRAM, program);
}
public static void main(String[] args)
{
MidiTest2 mt = new MidiTest2();
mt.run();
}
}
ChannelData类(不执行任何操作,但出于完整性考虑,我认为应该将其发布):
public class ChannelData {
MidiChannel channel;
boolean solo, mono, mute, sustain;
int velocity, pressure, bend, reverb;
int row, col, num;
public ChannelData(MidiChannel channel, int num) {
this.channel = channel;
this.num = num;
velocity = pressure = bend = reverb = 64;
}
public void setComponentStates() {
}
}
在程序中,我尝试用原声钢琴声音创建5个音符,并用电钢琴声音创建一个音符。 但是,即使在切换乐器之前创建了新音轨,所有音符仍会以电子钢琴的声音进行播放。
我已经尝试了5个小时左右来解决这个问题,但我全都没主意。
轨道可以帮助您自己的程序组织事件,但是它们不会以任何方式影响合成器。
要具有不同的设置,必须使用不同的通道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.