soiz1's picture
Upload folder using huggingface_hub
d46f4a3 verified
package com.mojang.blaze3d.audio;
import com.google.common.collect.Sets;
import com.mojang.logging.LogUtils;
import java.nio.IntBuffer;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.OptionalLong;
import java.util.Set;
import javax.annotation.Nullable;
import net.minecraft.SharedConstants;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.ALC;
import org.lwjgl.openal.ALC10;
import org.lwjgl.openal.ALC11;
import org.lwjgl.openal.ALCCapabilities;
import org.lwjgl.openal.ALCapabilities;
import org.lwjgl.openal.ALUtil;
import org.lwjgl.openal.SOFTHRTF;
import org.lwjgl.system.MemoryStack;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class Library {
static final Logger LOGGER = LogUtils.getLogger();
private static final int NO_DEVICE = 0;
private static final int DEFAULT_CHANNEL_COUNT = 30;
private long currentDevice;
private long context;
private boolean supportsDisconnections;
@Nullable
private String defaultDeviceName;
private static final Library.ChannelPool EMPTY = new Library.ChannelPool() {
@Nullable
@Override
public Channel acquire() {
return null;
}
@Override
public boolean release(Channel p_83708_) {
return false;
}
@Override
public void cleanup() {
}
@Override
public int getMaxCount() {
return 0;
}
@Override
public int getUsedCount() {
return 0;
}
};
private Library.ChannelPool staticChannels = EMPTY;
private Library.ChannelPool streamingChannels = EMPTY;
private final Listener listener = new Listener();
public Library() {
this.defaultDeviceName = getDefaultDeviceName();
}
public void init(@Nullable String p_231085_, boolean p_231086_) {
this.currentDevice = openDeviceOrFallback(p_231085_);
this.supportsDisconnections = false;
ALCCapabilities alccapabilities = ALC.createCapabilities(this.currentDevice);
if (OpenAlUtil.checkALCError(this.currentDevice, "Get capabilities")) {
throw new IllegalStateException("Failed to get OpenAL capabilities");
} else if (!alccapabilities.OpenALC11) {
throw new IllegalStateException("OpenAL 1.1 not supported");
} else {
this.setHrtf(alccapabilities.ALC_SOFT_HRTF && p_231086_);
try (MemoryStack memorystack = MemoryStack.stackPush()) {
IntBuffer intbuffer = memorystack.callocInt(3).put(6554).put(1).put(0).flip();
this.context = ALC10.alcCreateContext(this.currentDevice, intbuffer);
}
if (OpenAlUtil.checkALCError(this.currentDevice, "Create context")) {
throw new IllegalStateException("Unable to create OpenAL context");
} else {
ALC10.alcMakeContextCurrent(this.context);
int j = this.getChannelCount();
int k = Mth.clamp((int)Mth.sqrt((float)j), 2, 8);
int i = Mth.clamp(j - k, 8, 255);
this.staticChannels = new Library.CountingChannelPool(i);
this.streamingChannels = new Library.CountingChannelPool(k);
ALCapabilities alcapabilities = AL.createCapabilities(alccapabilities);
OpenAlUtil.checkALError("Initialization");
if (!alcapabilities.AL_EXT_source_distance_model) {
throw new IllegalStateException("AL_EXT_source_distance_model is not supported");
} else {
AL10.alEnable(512);
if (!alcapabilities.AL_EXT_LINEAR_DISTANCE) {
throw new IllegalStateException("AL_EXT_LINEAR_DISTANCE is not supported");
} else {
OpenAlUtil.checkALError("Enable per-source distance models");
LOGGER.info("OpenAL initialized on device {}", this.getCurrentDeviceName());
this.supportsDisconnections = ALC10.alcIsExtensionPresent(this.currentDevice, "ALC_EXT_disconnect");
}
}
}
}
}
private void setHrtf(boolean p_242278_) {
int i = ALC10.alcGetInteger(this.currentDevice, 6548);
if (i > 0) {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
IntBuffer intbuffer = memorystack.callocInt(10).put(6546).put(p_242278_ ? 1 : 0).put(6550).put(0).put(0).flip();
if (!SOFTHRTF.alcResetDeviceSOFT(this.currentDevice, intbuffer)) {
LOGGER.warn("Failed to reset device: {}", ALC10.alcGetString(this.currentDevice, ALC10.alcGetError(this.currentDevice)));
}
}
}
}
private int getChannelCount() {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
int i = ALC10.alcGetInteger(this.currentDevice, 4098);
if (OpenAlUtil.checkALCError(this.currentDevice, "Get attributes size")) {
throw new IllegalStateException("Failed to get OpenAL attributes");
}
IntBuffer intbuffer = memorystack.mallocInt(i);
ALC10.alcGetIntegerv(this.currentDevice, 4099, intbuffer);
if (OpenAlUtil.checkALCError(this.currentDevice, "Get attributes")) {
throw new IllegalStateException("Failed to get OpenAL attributes");
}
int j = 0;
while (j < i) {
int k = intbuffer.get(j++);
if (k == 0) {
break;
}
int l = intbuffer.get(j++);
if (k == 4112) {
return l;
}
}
}
return 30;
}
@Nullable
public static String getDefaultDeviceName() {
if (!ALC10.alcIsExtensionPresent(0L, "ALC_ENUMERATE_ALL_EXT")) {
return null;
} else {
ALUtil.getStringList(0L, 4115);
return ALC10.alcGetString(0L, 4114);
}
}
public String getCurrentDeviceName() {
String s = ALC10.alcGetString(this.currentDevice, 4115);
if (s == null) {
s = ALC10.alcGetString(this.currentDevice, 4101);
}
if (s == null) {
s = "Unknown";
}
return s;
}
public synchronized boolean hasDefaultDeviceChanged() {
String s = getDefaultDeviceName();
if (Objects.equals(this.defaultDeviceName, s)) {
return false;
} else {
this.defaultDeviceName = s;
return true;
}
}
private static long openDeviceOrFallback(@Nullable String p_193473_) {
OptionalLong optionallong = OptionalLong.empty();
if (p_193473_ != null) {
optionallong = tryOpenDevice(p_193473_);
}
if (optionallong.isEmpty()) {
optionallong = tryOpenDevice(getDefaultDeviceName());
}
if (optionallong.isEmpty()) {
optionallong = tryOpenDevice(null);
}
if (optionallong.isEmpty()) {
throw new IllegalStateException("Failed to open OpenAL device");
} else {
return optionallong.getAsLong();
}
}
private static OptionalLong tryOpenDevice(@Nullable String p_193476_) {
long i = ALC10.alcOpenDevice(p_193476_);
return i != 0L && !OpenAlUtil.checkALCError(i, "Open device") ? OptionalLong.of(i) : OptionalLong.empty();
}
public void cleanup() {
this.staticChannels.cleanup();
this.streamingChannels.cleanup();
ALC10.alcDestroyContext(this.context);
if (this.currentDevice != 0L) {
ALC10.alcCloseDevice(this.currentDevice);
}
}
public Listener getListener() {
return this.listener;
}
@Nullable
public Channel acquireChannel(Library.Pool p_83698_) {
return (p_83698_ == Library.Pool.STREAMING ? this.streamingChannels : this.staticChannels).acquire();
}
public void releaseChannel(Channel p_83696_) {
if (!this.staticChannels.release(p_83696_) && !this.streamingChannels.release(p_83696_)) {
throw new IllegalStateException("Tried to release unknown channel");
}
}
public String getDebugString() {
return String.format(
Locale.ROOT, "Sounds: %d/%d + %d/%d", this.staticChannels.getUsedCount(), this.staticChannels.getMaxCount(), this.streamingChannels.getUsedCount(), this.streamingChannels.getMaxCount()
);
}
public List<String> getAvailableSoundDevices() {
List<String> list = ALUtil.getStringList(0L, 4115);
return list == null ? Collections.emptyList() : list;
}
public boolean isCurrentDeviceDisconnected() {
return this.supportsDisconnections && ALC11.alcGetInteger(this.currentDevice, 787) == 0;
}
@OnlyIn(Dist.CLIENT)
interface ChannelPool {
@Nullable
Channel acquire();
boolean release(Channel p_83712_);
void cleanup();
int getMaxCount();
int getUsedCount();
}
@OnlyIn(Dist.CLIENT)
static class CountingChannelPool implements Library.ChannelPool {
private final int limit;
private final Set<Channel> activeChannels = Sets.newIdentityHashSet();
public CountingChannelPool(int p_83716_) {
this.limit = p_83716_;
}
@Nullable
@Override
public Channel acquire() {
if (this.activeChannels.size() >= this.limit) {
if (SharedConstants.IS_RUNNING_IN_IDE) {
Library.LOGGER.warn("Maximum sound pool size {} reached", this.limit);
}
return null;
} else {
Channel channel = Channel.create();
if (channel != null) {
this.activeChannels.add(channel);
}
return channel;
}
}
@Override
public boolean release(Channel p_83719_) {
if (!this.activeChannels.remove(p_83719_)) {
return false;
} else {
p_83719_.destroy();
return true;
}
}
@Override
public void cleanup() {
this.activeChannels.forEach(Channel::destroy);
this.activeChannels.clear();
}
@Override
public int getMaxCount() {
return this.limit;
}
@Override
public int getUsedCount() {
return this.activeChannels.size();
}
}
@OnlyIn(Dist.CLIENT)
public static enum Pool {
STATIC,
STREAMING;
}
}