Skip to content

Commit

Permalink
PlatformPlayer: Handle midi player creation and volume differently
Browse files Browse the repository at this point in the history
Might as well redo all of this, as the creation was the only part
that was still from the "older" FreeJ2ME implementation. Rework
this here to account better for the custom soundfont, and also
to have its critical bits available when needed for control and
such.
  • Loading branch information
AShiningRay committed Nov 19, 2024
1 parent 9fd2b17 commit 28dc753
Showing 1 changed file with 38 additions and 32 deletions.
70 changes: 38 additions & 32 deletions src/org/recompile/mobile/PlatformPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Synthesizer;
import javax.sound.midi.SysexMessage;
import javax.sound.midi.Track;
import javax.sound.sampled.AudioFormat;
Expand Down Expand Up @@ -362,18 +364,30 @@ private class midiPlayer extends audioplayer
private byte[] stream;
private Sequencer midi;
private Sequence midiSequence;
private Synthesizer synthesizer;
private Receiver receiver;

public midiPlayer(InputStream stream)
public midiPlayer(InputStream stream)
{
try
try
{
/* Open the midi stream without a receiver, so that we can load up the custom soundfont if available */
midi = MidiSystem.getSequencer(false);
this.stream = copyMediaData(stream);
}
catch (Exception e)
{
Mobile.log(Mobile.LOG_ERROR, PlatformPlayer.class.getPackage().getName() + "." + PlatformPlayer.class.getSimpleName() + ": " + "Couldn't load midi file:" + e.getMessage());

if (Manager.useCustomMidi && Manager.hasLoadedCustomMidi)
{
synthesizer = Manager.customSynth; // Use the custom synthesizer
} else
{
synthesizer = MidiSystem.getSynthesizer(); // Default synthesizer
}

synthesizer.open();
receiver = synthesizer.getReceiver();
midi.getTransmitter().setReceiver(receiver);
} catch (Exception e)
{
Mobile.log(Mobile.LOG_ERROR, PlatformPlayer.class.getPackage().getName() + "." + PlatformPlayer.class.getSimpleName() + ": " + "Couldn't load MIDI file: " + e.getMessage());
}
}

Expand All @@ -382,15 +396,6 @@ public void realize()
try
{
midi.open();
if(Manager.useCustomMidi && Manager.hasLoadedCustomMidi)
{
midi.getTransmitter().setReceiver(Manager.customSynth.getReceiver());
}
else
{
midi.getTransmitter().setReceiver(MidiSystem.getReceiver());
}

/* Make a new copy of the media stream, as realize() can be called more than once during the player's lifecycle */
midiSequence = MidiSystem.getSequence(new ByteArrayInputStream(stream));
midi.setSequence(midiSequence);
Expand Down Expand Up @@ -475,6 +480,8 @@ public long setMediaTime(long now)
public long getDuration() { return midi.getMicrosecondLength(); }

public boolean isRunning() { return midi.isRunning(); }

public Receiver getReceiver() { return receiver; }
}

private class wavPlayer extends audioplayer
Expand Down Expand Up @@ -918,25 +925,24 @@ public int setLevel(int level)
* from only making effective changes if needed.
*/

if(player instanceof midiPlayer)
if (player instanceof midiPlayer)
{

midiPlayer sequencer = (midiPlayer) player;
int midiVolume = isMuted() ? 0: (int) (this.level * 127 / 100);

/* Set volume for all channels, through Control Change command 7 */
for (Track track : sequencer.midiSequence.getTracks())
int midiVolume = isMuted() ? 0 : (int) (this.level * 127 / 100); // Convert to MIDI volume range
// Set volume for all channels through Control Change command 7
for (int channel = 0; channel < 16; channel++)
{
for (int i = 0; i < 16; i++)
{
/*
* This will make it so that volume changes take effect at the start of the midi stream.
* As far as i could test, all jars that have volume adjustment seem to start their streams
* from the very beginning after the volume is changed, so this is probably safe.
*/
try {track.add(new MidiEvent(new ShortMessage(ShortMessage.CONTROL_CHANGE, i, 7, midiVolume), 0)); }
catch (Exception e) { Mobile.log(Mobile.LOG_ERROR, PlatformPlayer.class.getPackage().getName() + "." + PlatformPlayer.class.getSimpleName() + ": " + "Midi setLevel failed: " + e.getMessage());}
}
try
{
ShortMessage volumeMessage = new ShortMessage();
volumeMessage.setMessage(ShortMessage.CONTROL_CHANGE, channel, 7, midiVolume); // Control Change 7 for volume
sequencer.getReceiver().send(volumeMessage, -1); // Send message to the receiver
}
catch (Exception e)
{
Mobile.log(Mobile.LOG_ERROR, PlatformPlayer.class.getPackage().getName() + "." + PlatformPlayer.class.getSimpleName() + ": " + "Midi setLevel failed: " + e.getMessage());
}
}
}
else if(player instanceof wavPlayer) /* Haven't found a jar that actually makes use of this yet - Scratch that: Shadow Shoot again */
Expand Down

0 comments on commit 28dc753

Please sign in to comment.