mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 20:20:30 +00:00
Enqueue audio when receiving it
While Minecraft will automatically push a new buffer when one is exhausted, this doesn't help if there's only a single buffer in the queue, and you end up with stutter. By enquing a buffer when receiving sound we ensure there's always something queued. I'm not 100% happy with this solution, but it does alleviate some of the concerns in #993. Also reduce the size of the client buffer to 0.5s from 1.5s. This is still enough to ensure seamless audio when the server is running slow (I tested at 13 tps, but should be able to go much worse).
This commit is contained in:
parent
8a1067940d
commit
aa36b49c50
@ -114,7 +114,9 @@ class DfpwmStream implements IAudioStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.flip();
|
result.flip();
|
||||||
return result;
|
|
||||||
|
// This is naughty, but ensures we're not enqueuing empty buffers when the stream is exhausted.
|
||||||
|
return result.remaining() == 0 ? null : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -122,4 +124,9 @@ class DfpwmStream implements IAudioStream
|
|||||||
{
|
{
|
||||||
buffers.clear();
|
buffers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty()
|
||||||
|
{
|
||||||
|
return buffers.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,20 @@ public class SpeakerInstance
|
|||||||
|
|
||||||
public synchronized void pushAudio( ByteBuf buffer )
|
public synchronized void pushAudio( ByteBuf buffer )
|
||||||
{
|
{
|
||||||
if( currentStream == null ) currentStream = new DfpwmStream();
|
SpeakerSound sound = this.sound;
|
||||||
|
|
||||||
|
DfpwmStream stream = currentStream;
|
||||||
|
if( stream == null ) stream = currentStream = new DfpwmStream();
|
||||||
|
boolean exhausted = stream.isEmpty();
|
||||||
currentStream.push( buffer );
|
currentStream.push( buffer );
|
||||||
|
|
||||||
|
// If we've got nothing left in the buffer, enqueue an additional one just in case.
|
||||||
|
if( exhausted && sound != null && sound.stream == stream && sound.source != null )
|
||||||
|
{
|
||||||
|
sound.executor.execute( () -> {
|
||||||
|
if( !sound.source.stopped() ) sound.source.pumpBuffers( 1 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playAudio( Vector3d position, float volume )
|
public void playAudio( Vector3d position, float volume )
|
||||||
|
@ -32,6 +32,9 @@ public class SpeakerManager
|
|||||||
|
|
||||||
event.getSource().attachBufferStream( sound.stream );
|
event.getSource().attachBufferStream( sound.stream );
|
||||||
event.getSource().play();
|
event.getSource().play();
|
||||||
|
|
||||||
|
sound.source = event.getSource();
|
||||||
|
sound.executor = event.getManager().executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SpeakerInstance getSound( UUID source )
|
public static SpeakerInstance getSound( UUID source )
|
||||||
|
@ -8,14 +8,18 @@ package dan200.computercraft.client.sound;
|
|||||||
import net.minecraft.client.audio.IAudioStream;
|
import net.minecraft.client.audio.IAudioStream;
|
||||||
import net.minecraft.client.audio.ITickableSound;
|
import net.minecraft.client.audio.ITickableSound;
|
||||||
import net.minecraft.client.audio.LocatableSound;
|
import net.minecraft.client.audio.LocatableSound;
|
||||||
|
import net.minecraft.client.audio.SoundSource;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.SoundCategory;
|
import net.minecraft.util.SoundCategory;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
public class SpeakerSound extends LocatableSound implements ITickableSound
|
public class SpeakerSound extends LocatableSound implements ITickableSound
|
||||||
{
|
{
|
||||||
|
SoundSource source;
|
||||||
|
Executor executor;
|
||||||
DfpwmStream stream;
|
DfpwmStream stream;
|
||||||
|
|
||||||
SpeakerSound( ResourceLocation sound, DfpwmStream stream, Vector3d position, float volume, float pitch )
|
SpeakerSound( ResourceLocation sound, DfpwmStream stream, Vector3d position, float volume, float pitch )
|
||||||
|
@ -28,7 +28,7 @@ class DfpwmState
|
|||||||
* The minimum size of the client's audio buffer. Once we have less than this on the client, we should send another
|
* The minimum size of the client's audio buffer. Once we have less than this on the client, we should send another
|
||||||
* batch of audio.
|
* batch of audio.
|
||||||
*/
|
*/
|
||||||
private static final long CLIENT_BUFFER = (long) (SECOND * 1.5);
|
private static final long CLIENT_BUFFER = (long) (SECOND * 0.5);
|
||||||
|
|
||||||
private static final int PREC = 10;
|
private static final int PREC = 10;
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ public abstract class SpeakerPeripheral implements IPeripheral
|
|||||||
// TODO: Use ArgumentHelpers instead?
|
// TODO: Use ArgumentHelpers instead?
|
||||||
int length = audio.length();
|
int length = audio.length();
|
||||||
if( length <= 0 ) throw new LuaException( "Cannot play empty audio" );
|
if( length <= 0 ) throw new LuaException( "Cannot play empty audio" );
|
||||||
if( length > 1024 * 16 * 8 ) throw new LuaException( "Audio data is too large" );
|
if( length > 128 * 1024 ) throw new LuaException( "Audio data is too large" );
|
||||||
|
|
||||||
DfpwmState state;
|
DfpwmState state;
|
||||||
synchronized( lock )
|
synchronized( lock )
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
public net.minecraft.client.renderer.FirstPersonRenderer func_178100_c(F)F # getMapAngleFromPitch
|
public net.minecraft.client.renderer.FirstPersonRenderer func_178100_c(F)F # getMapAngleFromPitch
|
||||||
public net.minecraft.client.renderer.FirstPersonRenderer func_228401_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;IFFLnet/minecraft/util/HandSide;)V # renderArmFirstPerson
|
public net.minecraft.client.renderer.FirstPersonRenderer func_228401_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;IFFLnet/minecraft/util/HandSide;)V # renderArmFirstPerson
|
||||||
public net.minecraft.client.renderer.FirstPersonRenderer func_228403_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;ILnet/minecraft/util/HandSide;)V # renderArm
|
public net.minecraft.client.renderer.FirstPersonRenderer func_228403_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;Lnet/minecraft/client/renderer/IRenderTypeBuffer;ILnet/minecraft/util/HandSide;)V # renderArm
|
||||||
|
|
||||||
# ClientTableFormatter
|
# ClientTableFormatter
|
||||||
public net.minecraft.client.gui.NewChatGui func_146234_a(Lnet/minecraft/util/text/ITextComponent;I)V # printChatMessageWithOptionalDeletion
|
public net.minecraft.client.gui.NewChatGui func_146234_a(Lnet/minecraft/util/text/ITextComponent;I)V # printChatMessageWithOptionalDeletion
|
||||||
public net.minecraft.client.gui.NewChatGui func_146242_c(I)V # deleteChatLine
|
public net.minecraft.client.gui.NewChatGui func_146242_c(I)V # deleteChatLine
|
||||||
public net.minecraft.client.Minecraft field_71462_r # currentScreen
|
public net.minecraft.client.Minecraft field_71462_r # currentScreen
|
||||||
|
|
||||||
|
# SpeakerInstance/SpeakerManager
|
||||||
|
public net.minecraft.client.audio.SoundSource func_216421_a(I)V # pumpBuffers
|
||||||
|
public net.minecraft.client.audio.SoundEngine field_217940_j # executor
|
||||||
|
Loading…
Reference in New Issue
Block a user