Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve audio playback for both wav and midi streams #199

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions src/javax/microedition/media/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,39 @@

public final class Manager
{

public static final String TONE_DEVICE_LOCATOR = "device://tone";

public static Player midiPlayers[] = new Player[32]; /* Default max amount of players in FreeJ2ME's config */
public static byte midiPlayersIndex = 0;

public static Player createPlayer(InputStream stream, String type) throws IOException, MediaException
{
//System.out.println("Create Player Stream "+type);
return new PlatformPlayer(stream, type);
if(type.equalsIgnoreCase("audio/mid") || type.equalsIgnoreCase("audio/midi") || type.equalsIgnoreCase("sp-midi") || type.equalsIgnoreCase("audio/spmidi"))
{
if(midiPlayersIndex >= midiPlayers.length) { midiPlayersIndex = 0; }
for(; midiPlayersIndex < midiPlayers.length; midiPlayersIndex++)
{
if(midiPlayers[midiPlayersIndex] == null) { break; } /* A null position means we can use it right away */
/* Otherwise, we only deallocate a position if it is not playing (running). */
else if(midiPlayers[midiPlayersIndex] != null && midiPlayers[midiPlayersIndex].getState() == Player.PREFETCHED)
{
midiPlayers[midiPlayersIndex].deallocate();
break;
}
/* If we ever reach this one, it's because all the other slots are used, and are playing */
else if(midiPlayersIndex == midiPlayers.length-1)
{
midiPlayers[midiPlayersIndex].deallocate();
break;
}
}
midiPlayers[midiPlayersIndex] = new PlatformPlayer(stream, type);
return midiPlayers[midiPlayersIndex++];
}
else
{
return new PlatformPlayer(stream, type);
}
}

public static Player createPlayer(String locator) throws MediaException
Expand All @@ -57,4 +82,8 @@ public static void playTone(int note, int duration, int volume)
System.out.println("Play Tone");
}

public static void updatePlayerNum(byte num)
{
midiPlayers = new Player[num];
}
}
37 changes: 27 additions & 10 deletions src/libretro/freej2me_libretro.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ int rotateScreen; /* acts as a boolean */
int phoneType; /* 0=standard, 1=nokia, 2=siemens, 3=motorola */
int gameFPS; /* Auto(0), 60, 30, 15 */
int soundEnabled; /* also acts as a boolean */
int maxMidiPlayers; /* Maximum amount of MIDI Players allowed on FreeJ2ME at any given time */
/* Variables used to manage the pointer speed when controlled from an analog stick */
int pointerXSpeed = 8;
int pointerYSpeed = 8;
Expand Down Expand Up @@ -331,6 +332,21 @@ static void check_variables(bool first_time_startup)
else if (!strcmp(var.value, "on")) { soundEnabled = 1; }
}

var.key = "freej2me_maxmidiplayers";
if (Environ(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "32")) { maxMidiPlayers = 32; }
else if (!strcmp(var.value, "1")) { maxMidiPlayers = 1; }
else if (!strcmp(var.value, "2")) { maxMidiPlayers = 2; }
else if (!strcmp(var.value, "4")) { maxMidiPlayers = 4; }
else if (!strcmp(var.value, "8")) { maxMidiPlayers = 8; }
else if (!strcmp(var.value, "16")) { maxMidiPlayers = 16; }
else if (!strcmp(var.value, "32")) { maxMidiPlayers = 32; }
else if (!strcmp(var.value, "48")) { maxMidiPlayers = 48; }
else if (!strcmp(var.value, "64")) { maxMidiPlayers = 64; }
else if (!strcmp(var.value, "96")) { maxMidiPlayers = 96; }
}


var.key = "freej2me_pointertype";
if (Environ(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
Expand Down Expand Up @@ -410,7 +426,7 @@ static void check_variables(bool first_time_startup)


/* Prepare a string to pass those core options to the Java app */
snprintf(options_update, PIPE_MAX_LEN, "FJ2ME_LR_OPTS:|%lux%lu|%d|%d|%d|%d", screenRes[0], screenRes[1], rotateScreen, phoneType, gameFPS, soundEnabled);
snprintf(options_update, PIPE_MAX_LEN, "FJ2ME_LR_OPTS:|%lux%lu|%d|%d|%d|%d|%d", screenRes[0], screenRes[1], rotateScreen, phoneType, gameFPS, soundEnabled, maxMidiPlayers);
optstrlen = strlen(options_update);

/* 0xD = 13, which is the special case where the java app will receive the updated configs */
Expand Down Expand Up @@ -470,23 +486,24 @@ void retro_init(void)
*/
check_variables(true);

char resArg[2][4], rotateArg[2], phoneArg[2], fpsArg[3], soundArg[2];
char resArg[2][4], rotateArg[2], phoneArg[2], fpsArg[3], soundArg[2], maxMidiArg[3];
sprintf(resArg[0], "%lu", screenRes[0]); /* Libretro config Width */
sprintf(resArg[1], "%lu", screenRes[1]); /* Libretro config Height */
sprintf(rotateArg, "%d", rotateScreen);
sprintf(phoneArg, "%d", phoneType);
sprintf(fpsArg, "%d", gameFPS);
sprintf(soundArg, "%d", soundEnabled);
sprintf(maxMidiArg, "%d", maxMidiPlayers);

/* start java process */
char *javapath;
Environ(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &javapath);
char *outPath = malloc(sizeof(char) * PATH_MAX_LENGTH);
fill_pathname_join(outPath, javapath, "freej2me-lr.jar", PATH_MAX_LENGTH);
char *params[] = { "java", "-jar", outPath, resArg[0], resArg[1], rotateArg, phoneArg, fpsArg, soundArg, NULL };
char *params[] = { "java", "-jar", outPath, resArg[0], resArg[1], rotateArg, phoneArg, fpsArg, soundArg, maxMidiArg, NULL };

log_fn(RETRO_LOG_INFO, "Passing params: %s | %s | %s | %s | %s | %s \n", *(params+3),
*(params+4), *(params+5), *(params+6), *(params+7), *(params+8));
log_fn(RETRO_LOG_INFO, "Passing params: %s | %s | %s | %s | %s | %s | %s \n", *(params+3),
*(params+4), *(params+5), *(params+6), *(params+7), *(params+8), *(params+9));
log_fn(RETRO_LOG_INFO, "Preparing to open FreeJ2ME's Java app (make sure freej2me-lr.jar is inside system/).\n");

#ifdef __linux__
Expand Down Expand Up @@ -974,8 +991,8 @@ pid_t javaOpen(char *cmd, char **params)
log_fn(RETRO_LOG_INFO, "Setting up java app's process and pipes...\n");

log_fn(RETRO_LOG_INFO, "Opening: %s %s %s ...\n", *(params+0), *(params+1), *(params+2));
log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s \n", *(params+3),
*(params+4), *(params+5), *(params+6), *(params+7), *(params+8));
log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s | %s \n", *(params+3),
*(params+4), *(params+5), *(params+6), *(params+7), *(params+8), *(params+9));

int fd_stdin = 0;
int fd_stdout = 1;
Expand Down Expand Up @@ -1098,15 +1115,15 @@ void javaOpen(char *cmd, char **params)
sprintf(cmdWin, "javaw -jar %s", cmd);

log_fn(RETRO_LOG_INFO, "Opening: %s \n", cmd);
for (int i = 3; i <= 8; i++) /* There are 8 cmd arguments for now */
for (int i = 3; i <= 9; i++) /* There are 8 cmd arguments for now */
{
log_fn(RETRO_LOG_INFO, "Processing arg %d: %s \n", i, *(params+i));
sprintf(cmdWin, "%s %s", cmdWin, *(params+i));
}

log_fn(RETRO_LOG_INFO, "Creating proc: %s \n", cmdWin);
log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s \n", *(params+3),
*(params+4), *(params+5), *(params+6), *(params+7), *(params+8));
log_fn(RETRO_LOG_INFO, "Params: %s | %s | %s | %s | %s | %s | %s\n", *(params+3),
*(params+4), *(params+5), *(params+6), *(params+7), *(params+8), *(params+9));

GetStartupInfo(&startInfo);
startInfo.dwFlags = STARTF_USESTDHANDLES;
Expand Down
47 changes: 45 additions & 2 deletions src/libretro/freej2me_libretro.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ struct retro_core_option_v2_definition core_options[] =
"freej2me_sound",
"Virtual Phone Settings > Virtual Phone Sound",
"Virtual Phone Sound",
"Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME (ID Software games such as DOOM II RPG having memory leaks with MIDI samples being one example). If a game doesn't run or has issues during longer sessions, try disabling this option.",
"Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME (ID Software games such as DOOM II RPG having memory leaks with MIDI samples being one example). If a game doesn't run or has issues during longer sessions, try disabling this option.",
"Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME. If a game doesn't run or has issues during longer sessions, try disabling this option.",
"Enables or disables the virtual phone's ability to load and play audio samples/tones. Some games require support for codecs not yet implemented, or have issues that can be worked around by disabling audio in FreeJ2ME. If a game doesn't run or has issues during longer sessions, try disabling this option.",
"vphone_settings",
{
{ "on", "On" },
Expand All @@ -160,6 +160,27 @@ struct retro_core_option_v2_definition core_options[] =
},
"on"
},
{
"freej2me_maxmidiplayers",
"Virtual Phone Settings > Max MIDI Players",
"Max MIDI Players",
"Sets the maximum amount of MIDI files that a given J2ME app can load up and play at any given time. Lower values may reduce memory usage and improve the VM's performance (especially on ID Software games like DOOM II RPG where setting this to 1 vastly reduces memory usage compared to the default), but some games might need bigger values.",
"Sets the maximum amount of MIDI files that a given J2ME app can load up and play at any given time. Lower values may reduce memory usage and improve the VM's performance (especially on ID Software games like DOOM II RPG where setting this to 1 vastly reduces memory usage compared to the default), but some games might need bigger values.",
"vphone_settings",
{
{ "1", "1" },
{ "2", "2" },
{ "4", "4" },
{ "8", "8" },
{ "16", "16" },
{ "32", "32" },
{ "48", "48" },
{ "64", "64" },
{ "96", "96" },
{ NULL, NULL },
},
"32"
},
{
"freej2me_pointertype",
"Advanced Settings > Pointer Type",
Expand Down Expand Up @@ -357,6 +378,24 @@ struct retro_core_option_definition core_options_v1 [] =
},
"on"
},
{
"freej2me_maxmidiplayers",
"Max MIDI Players",
"Sets the maximum amount of MIDI files that a given J2ME app can load up and play at any given time. Lower values may reduce memory usage and improve the VM's performance (especially on ID Software games like DOOM II RPG where setting this to 1 vastly reduces memory usage compared to the default), but some games might need bigger values.",
{
{ "1", "1" },
{ "2", "2" },
{ "4", "4" },
{ "8", "8" },
{ "16", "16" },
{ "32", "32" },
{ "48", "48" },
{ "64", "64" },
{ "96", "96" },
{ NULL, NULL },
},
"32"
},
{
"freej2me_pointertype",
"Pointer Type",
Expand Down Expand Up @@ -475,6 +514,10 @@ static const struct retro_variable vars[] =
"freej2me_sound",
"Virtual Phone Sound; on|off"
},
{ /* Max MIDI Players */
"freej2me_maxmidiplayers",
"Max MIDI Players: 32|1|2|4|8|16|48|64|96"
},
{ /* Pointer Type */
"freej2me_pointertype",
"Pointer Type; Mouse|Touch|None",
Expand Down
33 changes: 30 additions & 3 deletions src/org/recompile/freej2me/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.nio.file.Path;

import javax.microedition.lcdui.Graphics;
import javax.microedition.media.Manager;

import org.recompile.mobile.Mobile;
import org.recompile.mobile.PlatformImage;
Expand Down Expand Up @@ -65,13 +66,14 @@ public Config()
gc = lcd.getGraphics();

menu = new ArrayList<String[]>();
menu.add(new String[]{"Resume Game", "Display Size", "Sound", "Limit FPS", "Phone", "Rotate", "Exit"}); // 0 - Main Menu
menu.add(new String[]{"Resume Game", "Display Size", "Sound", "Limit FPS", "Phone", "Rotate", "Max MIDI Players", "Exit"}); // 0 - Main Menu
menu.add(new String[]{"96x65","96x96","104x80","128x128","132x176","128x160","176x208","176x220", "208x208", "240x320", "320x240", "240x400", "352x416", "360x640", "640x360" ,"480x800", "800x480"}); // 1 - Size
menu.add(new String[]{"Quit", "Main Menu"}); // 2 - Restart Notice
menu.add(new String[]{"On", "Off"}); // 3 - sound
menu.add(new String[]{"Standard", "Nokia", "Siemens","Motorola"}); // 4 - Phone
menu.add(new String[]{"On", "Off"}); // 5 - rotate
menu.add(new String[]{"Auto", "60 - Fast", "30 - Slow", "15 - Turtle"}); // 6 - FPS
menu.add(new String[]{"1", "2", "4", "8", "16", "32", "48", "64", "96"}); // 7 - Max amount of MIDI Players


onChange = new Runnable()
Expand Down Expand Up @@ -150,6 +152,7 @@ public void init()
if(!settings.containsKey("phone")) { settings.put("phone", "Standard"); }
if(!settings.containsKey("rotate")) { settings.put("rotate", "off"); }
if(!settings.containsKey("fps")) { settings.put("fps", "0"); }
if(!settings.containsKey("maxmidiplayers")) { settings.put("maxmidiplayers", "32"); }

int w = Integer.parseInt(settings.get("width"));
int h = Integer.parseInt(settings.get("height"));
Expand All @@ -160,6 +163,7 @@ public void init()
lcd = new PlatformImage(width, height);
gc = lcd.getGraphics();
}

}
catch (Exception e)
{
Expand Down Expand Up @@ -311,14 +315,15 @@ public void render()
for(int i=start; (i<(start+max))&(i<t.length); i++)
{
label = t[i];
if(menuid==0 && i>1 && i<7)
if(menuid==0 && i>1 && i<8)
{
switch(i)
{
case 2: label = label+": "+settings.get("sound"); break;
case 3: label = label+": "+settings.get("fps"); break;
case 4: label = label+": "+settings.get("phone"); break;
case 5: label = label+": "+settings.get("rotate"); break;
case 6: label = label+": "+settings.get("maxmidiplayers"); break;
}
}
if(i==itemid)
Expand Down Expand Up @@ -349,7 +354,8 @@ private void doMenuAction()
case 3: menuid=6; itemid=0; break; // fps
case 4: menuid=4; itemid=0; break; // phone
case 5: menuid=5; itemid=0; break; // rotate
case 6: System.exit(0); break;
case 6: menuid=7; itemid=0; break; // max MIDI Players
case 7: System.exit(0); break;
}
break;

Expand Down Expand Up @@ -397,6 +403,19 @@ private void doMenuAction()
menuid=0; itemid=0;
break;

case 7: // Max Midi Players
if(itemid==0) { updateMIDIPlayers("1"); }
if(itemid==1) { updateMIDIPlayers("2"); }
if(itemid==2) { updateMIDIPlayers("4"); }
if(itemid==3) { updateMIDIPlayers("8"); }
if(itemid==4) { updateMIDIPlayers("16"); }
if(itemid==5) { updateMIDIPlayers("32"); }
if(itemid==6) { updateMIDIPlayers("48"); }
if(itemid==7) { updateMIDIPlayers("64"); }
if(itemid==8) { updateMIDIPlayers("96"); }
menuid=2; itemid=0;
break;

}

render();
Expand Down Expand Up @@ -446,4 +465,12 @@ private void updateFPS(String value)
saveConfig();
onChange.run();
}

private void updateMIDIPlayers(String value)
{
System.out.println("Config: maxmidiplayers "+value);
settings.put("maxmidiplayers", value);
saveConfig();
onChange.run();
}
}
3 changes: 3 additions & 0 deletions src/org/recompile/freej2me/FreeJ2ME.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.io.File;
import java.io.FilenameFilter;
import javax.imageio.ImageIO;
import javax.microedition.media.Manager;

public class FreeJ2ME
{
Expand Down Expand Up @@ -349,6 +350,8 @@ private void settingsChanged()
resize();
main.setSize(lcdWidth*scaleFactor+xborder , lcdHeight*scaleFactor+yborder);
}

Manager.updatePlayerNum((byte) Integer.parseInt(config.settings.get("maxmidiplayers")));
}

private int getMobileKey(int keycode)
Expand Down
Loading
Loading