From 7f23b3b525106dcd46cb3bceff4e3d8bac6edf2a Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Tue, 22 Mar 2022 05:44:02 +0000 Subject: [PATCH] Allow sound instances to play custom audio streams (#8295) --- .../minecraft/client/MouseHandler.java.patch | 0 .../resources/sounds/SoundInstance.java.patch | 13 ++ .../client/sounds/SoundEngine.java.patch | 5 +- .../debug/client/AudioStreamTest.java | 111 ++++++++++++++++++ src/test/resources/META-INF/mods.toml | 2 + .../assets/audio_stream_test/sounds.json | 10 ++ .../assets/audio_stream_test/sounds/empty.ogg | Bin 0 -> 3478 bytes 7 files changed, 139 insertions(+), 2 deletions(-) mode change 100755 => 100644 patches/minecraft/net/minecraft/client/MouseHandler.java.patch create mode 100644 patches/minecraft/net/minecraft/client/resources/sounds/SoundInstance.java.patch create mode 100644 src/test/java/net/minecraftforge/debug/client/AudioStreamTest.java create mode 100644 src/test/resources/assets/audio_stream_test/sounds.json create mode 100644 src/test/resources/assets/audio_stream_test/sounds/empty.ogg diff --git a/patches/minecraft/net/minecraft/client/MouseHandler.java.patch b/patches/minecraft/net/minecraft/client/MouseHandler.java.patch old mode 100755 new mode 100644 diff --git a/patches/minecraft/net/minecraft/client/resources/sounds/SoundInstance.java.patch b/patches/minecraft/net/minecraft/client/resources/sounds/SoundInstance.java.patch new file mode 100644 index 0000000000..45019c31f7 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/resources/sounds/SoundInstance.java.patch @@ -0,0 +1,13 @@ +--- a/net/minecraft/client/resources/sounds/SoundInstance.java ++++ b/net/minecraft/client/resources/sounds/SoundInstance.java +@@ -50,4 +_,10 @@ + NONE, + LINEAR; + } ++ ++ /*================================ FORGE START ================================================*/ ++ ++ default java.util.concurrent.CompletableFuture getStream(net.minecraft.client.sounds.SoundBufferLibrary soundBuffers, Sound sound, boolean looping) { ++ return soundBuffers.m_120204_(sound.m_119787_(), looping); ++ } + } diff --git a/patches/minecraft/net/minecraft/client/sounds/SoundEngine.java.patch b/patches/minecraft/net/minecraft/client/sounds/SoundEngine.java.patch index e29c9c5ce2..47d136abba 100644 --- a/patches/minecraft/net/minecraft/client/sounds/SoundEngine.java.patch +++ b/patches/minecraft/net/minecraft/client/sounds/SoundEngine.java.patch @@ -26,7 +26,7 @@ WeighedSoundEvents weighedsoundevents = p_120313_.m_6775_(this.f_120217_); ResourceLocation resourcelocation = p_120313_.m_7904_(); if (weighedsoundevents == null) { -@@ -389,11 +_,13 @@ +@@ -389,18 +_,21 @@ p_194488_.m_83654_(vec3); p_194488_.m_83670_(flag); }); @@ -40,7 +40,8 @@ }); }); } else { -@@ -401,6 +_,7 @@ +- this.f_120222_.m_120204_(sound.m_119790_(), flag2).thenAccept((p_194504_) -> { ++ soundinstance.getStream(this.f_120222_, sound, flag2).thenAccept((p_194504_) -> { channelaccess$channelhandle.m_120154_((p_194498_) -> { p_194498_.m_83658_(p_194504_); p_194498_.m_83672_(); diff --git a/src/test/java/net/minecraftforge/debug/client/AudioStreamTest.java b/src/test/java/net/minecraftforge/debug/client/AudioStreamTest.java new file mode 100644 index 0000000000..771fe05348 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/client/AudioStreamTest.java @@ -0,0 +1,111 @@ +/* + * Minecraft Forge - Forge Development LLC + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.debug.client; + +import com.mojang.math.Vector3d; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.AbstractSoundInstance; +import net.minecraft.client.resources.sounds.Sound; +import net.minecraft.client.resources.sounds.SoundInstance; +import net.minecraft.client.sounds.AudioStream; +import net.minecraft.client.sounds.SoundBufferLibrary; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.client.event.ClientChatEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.loading.FMLLoader; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.BufferUtils; + +import javax.sound.sampled.AudioFormat; +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; + +/** + * Tests support for custom {@link AudioStream}s ({@link SoundInstance#getStream(SoundBufferLibrary, Sound, boolean)}. + * + * When the message "sine wave" is sent in chat, this should play a sine wave of 220Hz at the player's current position. + */ +@Mod(AudioStreamTest.MOD_ID) +public class AudioStreamTest +{ + private static final boolean ENABLED = true; + static final String MOD_ID = "audio_stream_test"; + + public AudioStreamTest() + { + if (ENABLED && FMLLoader.getDist().isClient()) + { + MinecraftForge.EVENT_BUS.addListener(ClientHandler::onClientChatEvent); + } + } + + public static class ClientHandler + { + public static void onClientChatEvent(ClientChatEvent event) + { + if (event.getMessage().equalsIgnoreCase("sine wave")) + { + event.setCanceled(true); + var mc = Minecraft.getInstance(); + mc.getSoundManager().play(new SineSound(mc.player.position())); + } + } + } + + public static class SineSound extends AbstractSoundInstance + { + protected SineSound(Vec3 position) + { + super(new ResourceLocation(MOD_ID, "sine_wave"), SoundSource.BLOCKS); + x = position.x; + y = position.y; + z = position.z; + } + + @NotNull + @Override + public CompletableFuture getStream(@NotNull SoundBufferLibrary soundBuffers, @NotNull Sound sound, boolean looping) + { + return CompletableFuture.completedFuture(new SineStream()); + } + } + + public static class SineStream implements AudioStream + { + private static final AudioFormat FORMAT = new AudioFormat(44100, 8, 1, false, false); + private static final double DT = 2 * Math.PI * 220 / 44100; + + private static double value = 0; + + @NotNull + @Override + public AudioFormat getFormat() + { + return FORMAT; + } + + @NotNull + @Override + public ByteBuffer read(int capacity) + { + ByteBuffer buffer = BufferUtils.createByteBuffer(capacity); + for(int i = 0; i < capacity; i++) + { + buffer.put(i, (byte) (Math.sin(value) * 127)); + value = (value + DT) % Math.PI; + } + return buffer; + } + + @Override + public void close() + { + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index f8402c0d02..66e7de192f 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -174,6 +174,8 @@ license="LGPL v2.1" modId="part_entity_test" [[mods]] modId="capabilities_test" +[[mods]] + modId="audio_stream_test" [[mods]] modId="custom_mob_bucket_test" [[mods]] diff --git a/src/test/resources/assets/audio_stream_test/sounds.json b/src/test/resources/assets/audio_stream_test/sounds.json new file mode 100644 index 0000000000..395be85874 --- /dev/null +++ b/src/test/resources/assets/audio_stream_test/sounds.json @@ -0,0 +1,10 @@ +{ + "sine_wave": { + "sounds": [ + { + "name": "audio_stream_test:empty", + "stream": true + } + ] + } +} diff --git a/src/test/resources/assets/audio_stream_test/sounds/empty.ogg b/src/test/resources/assets/audio_stream_test/sounds/empty.ogg new file mode 100644 index 0000000000000000000000000000000000000000..749d8e6c3d7bce7b0a85f26c9cd671da4e1752e3 GIT binary patch literal 3478 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 b{1$(E$ln_hFZ#8&hwJnIHWVEC|F!=Chb1q; literal 0 HcmV?d00001