package org.mctourney.autoreferee.util.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.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 Map<Integer, Integer> channelPatches; public NoteBlockReceiver(Set<Player> listeners) throws InvalidMidiDataException, IOException { this.listeners = listeners; 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; // get pitch and volume from the midi message float pitch = (float) ToneUtil.midiToPitch(message); float volume = VOLUME_RANGE * (message.getData2() / 127.0f); // get the correct instrument Integer patch = channelPatches.get(message.getChannel()); Sound instrument = Sound.NOTE_PIANO; if (patch != null) instrument = MidiUtil.patchToInstrument(patch); for (Player player : listeners) player.playSound(player.getLocation(), instrument, volume, pitch); } @Override public void close() { listeners.clear(); channelPatches.clear(); } }