我正在创建一个应用程序,用户可以在其中添加多个MIDI音符到一个集合,从这里他们可以按“播放”按钮,应用程序将遍历每个音符并通过扬声器播放。
我创建了一个MIDIMessage类,其中包含用户选择添加到列表中的注释的详细信息,存储的详细信息为Pitch,Velocity,Delay和Channel。
这些消息中的每一个都保存到类型为MIDIMessage的ArrayList。
然后我继续将集合的迭代器附加到迭代器对象并播放声音,同时集合中仍有一个元素尚未使用。
出于某种原因,即使我只在集合中添加一个音符,总会有两个音符以完全相同的音高,长度和速度播放。
同样,每个音符同时播放,无论集合中有多少音符,我都认为它们之间会有某种延迟。
以下是我目前使用的代码:
的MidiMessage:
package javatest;
public class MIDIMessage
{
private int pitch;
private int velocity;
private int channel;
public MIDIMessage(int p, int v, int c)
{
pitch = p;
velocity = v;
channel = c;
}
public int GetPitch()
{
return this.pitch;
}
public int GetVelocity()
{
return this.velocity;
}
public int GetChannel()
{
return this.channel;
}
}
在集合中添加备注:
public void AddToList()
{
int channel = jComboBoxChannels.getSelectedIndex();
int pitch = jComboBoxPitch.getSelectedIndex();
int velocity = ((Integer)jSpinnerVelocity.getValue());
collection.add(new MIDIMessage(pitch,velocity,channel));
}
播放音符:
try
{
jButton1.setEnabled(false);
Sequencer sequencer = MidiSystem.getSequencer();
sequencer.open();
Sequence sequence = new Sequence(Sequence.PPQ,1);
Track track = sequence.createTrack();
Iterator itr = collection.iterator();
int i = 0;
while(itr.hasNext())
{
MIDIMessage msg = (MIDIMessage)itr.next();
ShortMessage noteOnMsg = new ShortMessage();
//Signal/Channel/Pitch/Velocity
noteOnMsg.setMessage(ShortMessage.NOTE_ON, msg.GetChannel(),msg.GetPitch(),msg.GetVelocity());
ShortMessage noteOffMsg = new ShortMessage();
//Signal/Channel/Pitch/Velocity
noteOffMsg.setMessage(ShortMessage.NOTE_OFF,msg.GetChannel(),msg.GetPitch(),msg.GetVelocity());
track.add(new MidiEvent(noteOnMsg,0));
track.add(new MidiEvent(noteOffMsg,1));
//i = i+1;
}
sequencer.setSequence(sequence);
sequencer.setTempoInBPM(120);
sequencer.setLoopCount(1);
sequencer.start();
Thread.sleep(1000);
}
答案 0 :(得分:1)
我不确定为什么音符会播放两次,但这绝对是错误的:
track.add(new MidiEvent(noteOnMsg,0));
track.add(new MidiEvent(noteOffMsg,1));
正如您所见here,MidiEvent
由消息和MIDI标记组成。您总是在刻度线0上添加noteOnMsg
,在刻度线1上添加noteOffMsg
,这解释了为什么对于多个音符,它们都是同时播放的。你想做这样的事情:
startTick = 0;
while(itr.hasNext()) {
[...]
track.add(new MidiEvent(noteOnMsg,startTick));
track.add(new MidiEvent(noteOffMsg,startTick + how_long_the_note_is_played));
startTick += difference_between_this_note_and_the_next;
[...]
}
我不确定你的delay
意味着什么,如果你可以在这里使用它,那么我正在使用描述性变量名。
请注意,您必须在此处使用MIDI刻度 - 如果您想在MIDI刻度中转换秒数,请参阅this SO question(或更确切地说是答案):
[一个MIDI打勾多长时间?]
公式为
60000 / (BPM * PPQ)
(毫秒)。