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

Conversation

AShiningRay
Copy link
Contributor

@AShiningRay AShiningRay commented Oct 21, 2023

Fixes #197
Fixes #198

First off, i think it might result in conflicts if #193 is to be merged at some point, so i'll have to look at it later.

Now to the PR itself... this one contains fixes for audio looping on both MIDI and WAV streams, as well as a workaround to ID Software games' tendency to infinitely allocate new MIDI streams. The latter doesn't have a straightforward fix as far as i can tell, since InputStreams are used heavily throughout the audio players, though i'm open to discussions on how to improve this workaround or even do away with it by implementing a better fix.

As a bonus, this PR also comes packed with a few minor cleanups to the ADPCM decoder, as well as threading support for it, to make it a bit lighter at runtime.

It appears that most java games (Gameloft ones, like Asphalt 4,
Asphalt 6, Ferrari GT 3, Assassin's Creed Revelations and many
others for example) set the loop count on both midi and wav streams
as 1. This, however, translates to Java 8 looping those samples one
time more than needed, so every sfx and bgm playback repeated two
times instead of just one.

By reducing the requested loop count by one and checking cases
where J2ME apps might request loop count 0, pretty much all the
aforementioned games have their audio playback fixed.
DOOM II as well as Orcs and Elves II appear to constantly allocate
new MIDI samples whenever a different sample from the previously
played one is loaded, and never deallocate any of their samples,
resulting in memory leaks. While not the best solution to this,
we can work around those leaks by imposing a hard limit on how many
MIDI "channel slots" a J2ME app can populate.

Currently set at 36 slots, it seems to be big enough for anything i
tested so far, including Ferrari GT 3 which loads up many different
MIDI BGMs alongside wav files (unrestricted, can allocate as many
as needed) during a race.
Swapping them to byte variables helps indicate that they should not
receive larger values.
The main thread on FreeJ2ME is already pretty busy with graphics
and everything else, we don't need ADPCM decoding clogging things
up even further. This should help make decoding faster and reduce
stuttering.
Copy link
Collaborator

@recompileorg recompileorg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"There are only two hard things in Computer Science: cache invalidation and naming things." --Phil Karlton

"MIDI Channel" has a specific meaning in MIDI, which is very different from how it's being used here. As for what to call it, that's up for debate. I thought "MIDI Stream" might be okay, though I can think of reasons why that could also be confusing... "MIDI Source" or "MIDI Audio Source"?

Anyhow, sorry that I've been so absent this year. Things should slow down quite a bit in November, baring unforeseen disaster. I'll try to make my freej2me backlog a priority then.

@AShiningRay
Copy link
Contributor Author

"MIDI Channel" has a specific meaning in MIDI, which is very different from how it's being used here. As for what to call it, that's up for debate. I thought "MIDI Stream" might be okay, though I can think of reasons why that could also be confusing... "MIDI Source" or "MIDI Audio Source"?

Yeah, couldn't think of a good way of naming those either. Only settled for "channels" (with quotation marks) because i thought it would kinda work by imposing a max limit on how many streams would be able to be played at any given time, similar to FM chips with a limited amount set of channels for FM Synthesis.

Still, i also don't like calling those "channels", just couldn't find any better naming scheme for them just yet... "MIDI Players" could also do, but this really feels like something that should come with a tooltip, description or something along those lines to better explain what it's about.

Instead of relying on a fixed value for the max, a user setting
for that allows more control and fine tuning for specific apps.
Previously, the logic behind deallocating streams only took into
account if the player index had reached the end of the array, and
started deallocating from its first position onwards. This was a
problem because it is possible that some of those positions would
still be running when FreeJ2ME went to deallocate them.

Now it will also take into account whether the current position
is running or not, and will only forcefully deallocate a position
that's running if the entire array is allocated, and all the
players are running, to make space for a new one.
@AShiningRay AShiningRay mentioned this pull request Oct 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants