Skip to content

Commit

Permalink
Generate updated MobiVM MetalANGLE backend (#7377)
Browse files Browse the repository at this point in the history
* Generate MobiVM MetalANGLE backend

* feat: Add CHANGES for iOS AudioDevice

---------

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
Berstanio and actions-user committed Apr 13, 2024
1 parent 7c6db62 commit d603706
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[1.12.2-SNAPSHOT]
- [BREAKING CHANGE] GWT: Updated to 2.10.0. `com.google.jsinterop:jsinterop-annotations:2.0.2:sources` must be added as a dependency to your html project dependencies.
- [BREAKING CHANGE] Android: Minimum API level is now level 19 (Android 4.4)
- iOS: The iOS backend now implements AudioDevice. It can be configured through IOSApplicationConfiguration with audioDeviceBufferSize/audioDeviceBufferCount
- Fixed GlyphLayout for fixed width glyph offsets at the start and end of lines.
- Fixed scene2d.ui layout for fractional positions and sizes.
- libGDX is now built using Java 17 due to Gradle 8 requirements.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ public class IOSApplicationConfiguration {
/** The maximum number of threads to use for network requests. Default is {@link Integer#MAX_VALUE}. */
public int maxNetThreads = Integer.MAX_VALUE;

/** The minimal buffer size of the audio device. Below 2048 can lead to buggy behavior. */
public int audioDeviceBufferSize = 512;

/** How many buffers to use for audio device */
public int audioDeviceBufferCount = 9;

/** whether to use audio or not. Default is <code>true</code> * */
public boolean useAudio = true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

import org.robovm.apple.foundation.NSObject;
import org.robovm.objc.ObjCRuntime;
import org.robovm.objc.annotation.Method;
import org.robovm.objc.annotation.NativeClass;
import org.robovm.rt.bro.annotation.Library;
import org.robovm.rt.bro.ptr.VoidPtr;

/** DO NOT EDIT THIS FILE - it is machine generated
* @author Niklas Therning */
Expand All @@ -16,4 +18,10 @@ public class ALBuffer extends NSObject {
static {
ObjCRuntime.bind(ALBuffer.class);
}

@Method(selector = "bufferId")
public native int bufferId ();

@Method(selector = "initWithName:data:size:format:frequency:")
public native ALBuffer initWithNameDataSizeFormatFrequency (String name, VoidPtr data, int size, int format, int frequency);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*DO NOT EDIT THIS FILE - it is machine generated*/

package com.badlogic.gdx.backends.iosrobovm.objectal;

/** DO NOT EDIT THIS FILE - it is machine generated */
public class ALConsts {

public static int AL_FORMAT_MONO16 = 0x1101;

public static int AL_FORMAT_STEREO16 = 0x1103;
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,19 @@ public class ALSource extends NSObject {

@Method(selector = "setLooping:")
public native void setLooping (boolean shouldLoop);

@Method(selector = "buffersProcessed")
public native int buffersProcessed ();

@Method(selector = "unqueueBuffer:")
public native boolean unqueueBuffer (ALBuffer buffer);

@Method(selector = "queueBuffer:")
public native boolean queueBuffer (ALBuffer buffer);

@Method(selector = "playing")
public native boolean playing ();

@Method(selector = "play")
public native int play ();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*DO NOT EDIT THIS FILE - it is machine generated*/

package com.badlogic.gdx.backends.iosrobovm.objectal;

import org.robovm.apple.foundation.NSObject;
import org.robovm.objc.ObjCRuntime;
import org.robovm.objc.annotation.Method;
import org.robovm.objc.annotation.NativeClass;
import org.robovm.rt.bro.annotation.Library;
import org.robovm.rt.bro.ptr.VoidPtr;

/** DO NOT EDIT THIS FILE - it is machine generated
* @author Jile Gao */
@Library(Library.INTERNAL)
@NativeClass
public class ALWrapper extends NSObject {

static {
ObjCRuntime.bind(ALWrapper.class);
}

@Method(selector = "bufferData:format:data:size:frequency:")
public static native boolean bufferData (int bufferId, int format, VoidPtr data, int size, int frequency);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public final class OALAudioSession extends NSObject {
@Method
public native static OALAudioSession sharedInstance ();

@Method
public native boolean interrupted ();

@Method
public native void forceEndInterruption ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ public OALIOSAudio (IOSApplicationConfiguration config) {
audio.setAllowIpod(config.allowIpod);
audio.setHonorSilentSwitch(!config.overrideRingerSwitch);
} else
Gdx.app.error("IOSAudio", "No OALSimpleAudio instance available, audio will not be availabe");
Gdx.app.error("IOSAudio", "No OALSimpleAudio instance available, audio will not be available");
}

@Override
public AudioDevice newAudioDevice (int samplingRate, boolean isMono) {
// TODO Auto-generated method stub
return null;
return new OALIOSAudioDevice(samplingRate, isMono, config.audioDeviceBufferSize, config.audioDeviceBufferCount);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*DO NOT EDIT THIS FILE - it is machine generated*/

package com.badlogic.gdx.backends.iosrobovm.objectal;

import com.badlogic.gdx.audio.AudioDevice;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.ptr.ShortPtr;
import org.robovm.rt.bro.ptr.VoidPtr;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.List;
import static com.badlogic.gdx.backends.iosrobovm.objectal.ALConsts.AL_FORMAT_MONO16;
import static com.badlogic.gdx.backends.iosrobovm.objectal.ALConsts.AL_FORMAT_STEREO16;

/** DO NOT EDIT THIS FILE - it is machine generated
* @author Jile Gao
* @author Berstanio */
class OALIOSAudioDevice implements AudioDevice {

private ALSource alSource;

private List<ALBuffer> alBuffers = new ArrayList<>();

private List<ALBuffer> alBuffersFree = new ArrayList<>();

private final int samplingRate;

private final boolean isMono;

private final int format;

private final ShortBuffer tmpBuffer;

private final int minSize;

private final int latency;

OALIOSAudioDevice (int samplingRate, boolean isMono, int minSize, int bufferCount) {
this.samplingRate = samplingRate;
this.isMono = isMono;
this.format = isMono ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
this.minSize = minSize;
tmpBuffer = ShortBuffer.allocate(minSize);
latency = minSize / (isMono ? 1 : 2) / bufferCount;
alSource = new ALSource();
for (int i = 0; i < bufferCount; i++) {
ALBuffer buffer = new ALBuffer().initWithNameDataSizeFormatFrequency("test", Struct.allocate(VoidPtr.class, 1), 2,
format, samplingRate);
alBuffersFree.add(buffer);
}
}

@Override
public boolean isMono () {
return isMono;
}

@Override
public void writeSamples (short[] samples, int offset, int numSamples) {
if (numSamples < 0) throw new IllegalArgumentException("numSamples cannot be < 0.");
ShortPtr shortPtr;
if (numSamples + tmpBuffer.position() >= minSize) {
shortPtr = Struct.allocate(ShortPtr.class, numSamples + tmpBuffer.position());
shortPtr.set(tmpBuffer.array(), 0, tmpBuffer.position());
shortPtr.next(tmpBuffer.position()).set(samples, offset, numSamples);
numSamples += tmpBuffer.position();
tmpBuffer.position(0);
} else {
tmpBuffer.put(samples, offset, numSamples);
return;
}
while (alBuffersFree.isEmpty()) {
if (OALAudioSession.sharedInstance().interrupted()) {
try {
Thread.sleep(2);
} catch (InterruptedException ignored) {
}
return;
}
int toFree = Math.min(alSource.buffersProcessed(), alBuffers.size());
for (int j = 0; j < toFree; j++) {
ALBuffer alBuffer = alBuffers.get(0);
if (alSource.unqueueBuffer(alBuffer)) {
alBuffersFree.add(alBuffer);
alBuffers.remove(alBuffer);
} else {
break;
}
}
if (alBuffersFree.isEmpty()) {
try {
Thread.sleep(2);
} catch (InterruptedException ignored) {
}
}
}
ALBuffer buffer = alBuffersFree.remove(0);
ALWrapper.bufferData(buffer.bufferId(), format, shortPtr.as(VoidPtr.class), numSamples * 2, samplingRate);
if (alSource.queueBuffer(buffer)) {
alBuffers.add(buffer);
}
if (!alSource.playing()) {
alSource.play();
}
}

@Override
public void writeSamples (float[] samples, int offset, int numSamples) {
short[] shortSamples = new short[samples.length];
for (int i = offset, j = 0; i < samples.length; i++, j++) {
float fValue = samples[i];
if (fValue > 1) fValue = 1;
if (fValue < -1) fValue = -1;
short value = (short)(fValue * Short.MAX_VALUE);
shortSamples[j] = value;
}
writeSamples(shortSamples, offset, numSamples);
}

@Override
public int getLatency () {
return latency;
}

@Override
public void dispose () {
alSource.stop();
alBuffers = null;
alBuffersFree = null;
alSource = null;
}

@Override
public void setVolume (float volume) {
alSource.setVolume(volume);
}

@Override
public void pause () {
alSource.setPaused(true);
}

@Override
public void resume () {
alSource.setPaused(false);
}
}

0 comments on commit d603706

Please sign in to comment.