/
NoteBlockReceiver.java
105 lines (85 loc) · 3.02 KB
/
NoteBlockReceiver.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package net.aufdemrand.denizen.utilities.midi;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.Receiver;
import javax.sound.midi.ShortMessage;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import com.google.common.collect.Maps;
/**
* Midi Receiver for processing note events.
*
* @author authorblues
*/
public class NoteBlockReceiver implements Receiver
{
private static final float VOLUME_RANGE = 10.0f;
private final Set<Player> listeners;
private final Location location;
private final Map<Integer, Integer> channelPatches;
public NoteBlockReceiver(Set<Player> listeners) throws InvalidMidiDataException, IOException
{
this.listeners = listeners;
this.location = null;
this.channelPatches = Maps.newHashMap();
}
public NoteBlockReceiver(Location location) throws InvalidMidiDataException, IOException
{
this.listeners = null;
this.location = location;
this.channelPatches = Maps.newHashMap();
}
@Override
public void send(MidiMessage m, long time)
{
if (m instanceof ShortMessage)
{
ShortMessage smessage = (ShortMessage) m;
int chan = smessage.getChannel();
switch (smessage.getCommand())
{
case ShortMessage.PROGRAM_CHANGE:
int patch = smessage.getData1();
channelPatches.put(chan, patch);
break;
case ShortMessage.NOTE_ON:
this.playNote(smessage);
break;
case ShortMessage.NOTE_OFF:
break;
}
}
}
public void playNote(ShortMessage message)
{
// if this isn't a NOTE_ON message, we can't play it
if (ShortMessage.NOTE_ON != message.getCommand()) return;
int channel = message.getChannel();
// If this is a percussion channel, return
if (channel == 9) return;
// get the correct instrument
Integer patch = channelPatches.get(channel);
// get pitch and volume from the midi message
float pitch = (float) ToneUtil.midiToPitch(message);
float volume = VOLUME_RANGE * (message.getData2() / 127.0f);
Sound instrument = Sound.NOTE_PIANO;
if (patch != null) instrument = MidiUtil.patchToInstrument(patch);
if (location != null) {
location.getWorld().playSound(location, instrument, volume, pitch);
}
else {
for (Player player : listeners)
player.playSound(player.getLocation(), instrument, volume, pitch);
}
}
@Override
public void close()
{
listeners.clear();
channelPatches.clear();
}
}