forked from jzitnik/twodcraft
refactor(sounds): Rewritten code for sound to ogg
Now SoundPlayer class supports only .ogg files instead of wav file which can reduce the final .jar file size drastically. It uses library.
This commit is contained in:
parent
a84d3bec00
commit
433dbf6f96
5
pom.xml
5
pom.xml
@ -128,6 +128,11 @@
|
|||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
<version>1.5.18</version> <!-- latest at the time -->
|
<version>1.5.18</version> <!-- latest at the time -->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.trilarion</groupId>
|
||||||
|
<artifactId>java-vorbis-support</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -282,7 +282,6 @@ public class Game extends AutoTransientSupport {
|
|||||||
|
|
||||||
gameStates.dependencies.eventHandlerProvider.handleMine(screenRenderer, this, x, y);
|
gameStates.dependencies.eventHandlerProvider.handleMine(screenRenderer, this, x, y);
|
||||||
|
|
||||||
screenRenderer.render(this);
|
|
||||||
|
|
||||||
for (Block block : blocksCopy) {
|
for (Block block : blocksCopy) {
|
||||||
if (block.getClass().isAnnotationPresent(MineSound.class)) {
|
if (block.getClass().isAnnotationPresent(MineSound.class)) {
|
||||||
@ -294,6 +293,8 @@ public class Game extends AutoTransientSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
screenRenderer.render(this);
|
||||||
|
|
||||||
update(screenRenderer);
|
update(screenRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package cz.jzitnik.game.config;
|
package cz.jzitnik.game.config;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class Configuration {
|
public class Configuration implements Serializable {
|
||||||
private int soundVolume = 100; // 0-100
|
private int soundVolume = 100; // 0-100
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,20 @@ public class Sound {
|
|||||||
|
|
||||||
var annotation = map.get(soundKey);
|
var annotation = map.get(soundKey);
|
||||||
|
|
||||||
try {
|
var resources = annotation.resourceLocation();
|
||||||
var resources = annotation.resourceLocation();
|
var resource = resources[random.nextInt(resources.length)];
|
||||||
|
|
||||||
var resource = resources[random.nextInt(resources.length)];
|
var typeVolue = annotation.type().getVolume();
|
||||||
SoundPlayer.playSound(resource, volume);
|
|
||||||
} catch (LineUnavailableException | IOException | UnsupportedAudioFileException | InterruptedException e) {
|
int totalVolume = (int) ((volume + typeVolue) * 100) / 200;
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
new Thread(() -> {
|
||||||
}
|
try {
|
||||||
|
SoundPlayer.playSound(resource);
|
||||||
|
} catch (LineUnavailableException | IOException | UnsupportedAudioFileException | InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,7 @@ public enum SoundKey {
|
|||||||
GRASS_WALKING,
|
GRASS_WALKING,
|
||||||
|
|
||||||
GRAVEL,
|
GRAVEL,
|
||||||
GRAVEL_WALKING
|
GRAVEL_WALKING,
|
||||||
|
|
||||||
|
WOOD,
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
package cz.jzitnik.game.core.sound;
|
package cz.jzitnik.game.core.sound;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public enum SoundType {
|
public enum SoundType {
|
||||||
BLOCK
|
BLOCK(100);
|
||||||
|
|
||||||
|
// TODO: Volume is not currently used but will be probably used in future to better normalize the sound volume
|
||||||
|
private final int volume;
|
||||||
|
|
||||||
|
SoundType(int volume) {
|
||||||
|
this.volume = volume;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ import cz.jzitnik.game.core.sound.SoundKey;
|
|||||||
import cz.jzitnik.game.core.sound.SoundType;
|
import cz.jzitnik.game.core.sound.SoundType;
|
||||||
|
|
||||||
@SoundRegistry(key = SoundKey.GRASS, resourceLocation = {
|
@SoundRegistry(key = SoundKey.GRASS, resourceLocation = {
|
||||||
"grass/grass1.wav",
|
"grass/grass1.ogg",
|
||||||
"grass/grass2.wav",
|
"grass/grass2.ogg",
|
||||||
"grass/grass3.wav",
|
"grass/grass3.ogg",
|
||||||
"grass/grass4.wav"
|
"grass/grass4.ogg"
|
||||||
}, type = SoundType.BLOCK)
|
}, type = SoundType.BLOCK)
|
||||||
public class GrassSound {
|
public class GrassSound {
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,12 @@ import cz.jzitnik.game.core.sound.SoundKey;
|
|||||||
import cz.jzitnik.game.core.sound.SoundType;
|
import cz.jzitnik.game.core.sound.SoundType;
|
||||||
|
|
||||||
@SoundRegistry(key = SoundKey.GRASS_WALKING, resourceLocation = {
|
@SoundRegistry(key = SoundKey.GRASS_WALKING, resourceLocation = {
|
||||||
"grass/walk1.wav",
|
"grass/walk1.ogg",
|
||||||
"grass/walk2.wav",
|
"grass/walk2.ogg",
|
||||||
"grass/walk3.wav",
|
"grass/walk3.ogg",
|
||||||
"grass/walk4.wav",
|
"grass/walk4.ogg",
|
||||||
"grass/walk5.wav",
|
"grass/walk5.ogg",
|
||||||
"grass/walk6.wav",
|
"grass/walk6.ogg",
|
||||||
}, type = SoundType.BLOCK)
|
}, type = SoundType.BLOCK)
|
||||||
public class GrassWalkingSound {
|
public class GrassWalkingSound {
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package cz.jzitnik.game.core.sound.registry;
|
||||||
|
|
||||||
|
import cz.jzitnik.game.annotations.SoundRegistry;
|
||||||
|
import cz.jzitnik.game.core.sound.SoundKey;
|
||||||
|
import cz.jzitnik.game.core.sound.SoundType;
|
||||||
|
|
||||||
|
@SoundRegistry(key = SoundKey.WOOD, resourceLocation = {
|
||||||
|
"wood/wood1.ogg",
|
||||||
|
}, type = SoundType.BLOCK)
|
||||||
|
public class WoodSound {
|
||||||
|
}
|
@ -3,11 +3,16 @@ package cz.jzitnik.game.entities.items.registry.blocks.blocks;
|
|||||||
import cz.jzitnik.game.SpriteLoader;
|
import cz.jzitnik.game.SpriteLoader;
|
||||||
import cz.jzitnik.game.annotations.BlockRegistry;
|
import cz.jzitnik.game.annotations.BlockRegistry;
|
||||||
import cz.jzitnik.game.annotations.Flamable;
|
import cz.jzitnik.game.annotations.Flamable;
|
||||||
|
import cz.jzitnik.game.annotations.MineSound;
|
||||||
|
import cz.jzitnik.game.annotations.PlaceSound;
|
||||||
|
import cz.jzitnik.game.core.sound.SoundKey;
|
||||||
import cz.jzitnik.game.entities.Block;
|
import cz.jzitnik.game.entities.Block;
|
||||||
import cz.jzitnik.game.entities.items.ItemType;
|
import cz.jzitnik.game.entities.items.ItemType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@MineSound(SoundKey.WOOD)
|
||||||
|
@PlaceSound(SoundKey.WOOD)
|
||||||
@Flamable
|
@Flamable
|
||||||
@BlockRegistry("oak_log")
|
@BlockRegistry("oak_log")
|
||||||
public class OakLogBlock extends Block {
|
public class OakLogBlock extends Block {
|
||||||
|
@ -5,7 +5,6 @@ import cz.jzitnik.game.entities.SteveData;
|
|||||||
import cz.jzitnik.game.Game;
|
import cz.jzitnik.game.Game;
|
||||||
import cz.jzitnik.game.sprites.Air;
|
import cz.jzitnik.game.sprites.Air;
|
||||||
import cz.jzitnik.game.sprites.SimpleSprite;
|
import cz.jzitnik.game.sprites.SimpleSprite;
|
||||||
import cz.jzitnik.game.sprites.Steve;
|
|
||||||
import cz.jzitnik.game.blocks.Chest;
|
import cz.jzitnik.game.blocks.Chest;
|
||||||
import cz.jzitnik.game.blocks.Furnace;
|
import cz.jzitnik.game.blocks.Furnace;
|
||||||
import cz.jzitnik.game.ui.Escape;
|
import cz.jzitnik.game.ui.Escape;
|
||||||
|
@ -1,32 +1,58 @@
|
|||||||
package cz.jzitnik.tui;
|
package cz.jzitnik.tui;
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import javax.sound.sampled.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SoundPlayer {
|
public class SoundPlayer {
|
||||||
public static Clip playSound(String filePath, int volume)
|
public static void playSound(String filePath)
|
||||||
throws LineUnavailableException, IOException, UnsupportedAudioFileException, InterruptedException {
|
throws LineUnavailableException, IOException, UnsupportedAudioFileException, InterruptedException {
|
||||||
|
if (!filePath.endsWith(".ogg")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
log.info("Loading resource: {}", "sounds/" + filePath);
|
log.info("Loading resource: {}", "sounds/" + filePath);
|
||||||
var soundFile = SoundPlayer.class.getClassLoader().getResourceAsStream("sounds/" + filePath);
|
|
||||||
AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundFile);
|
|
||||||
Clip clip = AudioSystem.getClip();
|
|
||||||
clip.open(audioStream);
|
|
||||||
|
|
||||||
FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
|
var file = SoundPlayer.class.getClassLoader().getResourceAsStream("sounds/" + filePath);
|
||||||
float min = volumeControl.getMinimum();
|
AudioInputStream audioStream = AudioSystem.getAudioInputStream(file);
|
||||||
float max = volumeControl.getMaximum();
|
AudioFormat baseFormat = audioStream.getFormat();
|
||||||
float gain = min + (max - min) * (volume / 100.0f);
|
|
||||||
volumeControl.setValue(gain);
|
|
||||||
|
|
||||||
log.info("Starting to play {}", filePath);
|
// Convert the audio format to PCM_SIGNED
|
||||||
clip.start();
|
AudioFormat targetFormat = new AudioFormat(
|
||||||
|
AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
baseFormat.getSampleRate(),
|
||||||
|
16,
|
||||||
|
baseFormat.getChannels(),
|
||||||
|
baseFormat.getChannels() * 2,
|
||||||
|
baseFormat.getSampleRate(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
// Thread.sleep(clip.getMicrosecondLength() / 1000);
|
// Apply the format change to the stream
|
||||||
|
AudioInputStream dataIn = AudioSystem.getAudioInputStream(targetFormat, audioStream);
|
||||||
|
|
||||||
return clip;
|
byte[] buffer = new byte[8192]; // Larger buffer to reduce read/write operations
|
||||||
|
DataLine.Info info = new DataLine.Info(SourceDataLine.class, targetFormat);
|
||||||
|
|
||||||
|
try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) {
|
||||||
|
if (line != null) {
|
||||||
|
line.open(targetFormat);
|
||||||
|
line.start();
|
||||||
|
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = dataIn.read(buffer, 0, buffer.length)) != -1) {
|
||||||
|
line.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the line is fully flushed before stopping
|
||||||
|
line.drain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close streams after use
|
||||||
|
dataIn.close();
|
||||||
|
audioStream.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
src/main/resources/sounds/grass/grass1.ogg
Normal file
BIN
src/main/resources/sounds/grass/grass1.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/grass2.ogg
Normal file
BIN
src/main/resources/sounds/grass/grass2.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/grass3.ogg
Normal file
BIN
src/main/resources/sounds/grass/grass3.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/grass4.ogg
Normal file
BIN
src/main/resources/sounds/grass/grass4.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/walk1.ogg
Normal file
BIN
src/main/resources/sounds/grass/walk1.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/walk2.ogg
Normal file
BIN
src/main/resources/sounds/grass/walk2.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/walk3.ogg
Normal file
BIN
src/main/resources/sounds/grass/walk3.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/walk4.ogg
Normal file
BIN
src/main/resources/sounds/grass/walk4.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/walk5.ogg
Normal file
BIN
src/main/resources/sounds/grass/walk5.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/grass/walk6.ogg
Normal file
BIN
src/main/resources/sounds/grass/walk6.ogg
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/main/resources/sounds/wood/wood1.ogg
Normal file
BIN
src/main/resources/sounds/wood/wood1.ogg
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user