tcr/java/src/game/init/SoundEvent.java

276 lines
8.1 KiB
Java
Raw Normal View History

2025-03-11 00:23:54 +01:00
package game.init;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import game.log.Log;
2025-03-11 00:23:54 +01:00
import game.rng.Random;
import game.util.FileUtils;
2025-03-11 00:23:54 +01:00
public enum SoundEvent {
CLOTH("cloth1", "cloth2", "cloth3", "cloth4"),
GRASS("grass1", "grass2", "grass3", "grass4"),
GRAVEL("gravel1", "gravel2", "gravel3", "gravel4"),
SAND("sand1", "sand2", "sand3", "sand4"),
SNOW("snow1", "snow2", "snow3", "snow4"),
STONE("stone1", "stone2", "stone3", "stone4"),
WOOD("wood1", "wood2", "wood3", "wood4"),
GLASS("glass1", "glass2", "glass3"),
SPELL("spell"),
TELEPORT("teleport"),
TELEPORT_REV("teleport_back"),
FIREBALL("fireball"),
METAL("metal1", "metal2", "metal3"),
METALHIT("metalhit1", "metalhit2"),
ANVIL_BREAK("anvil_break"),
ANVIL_LAND("anvil_land"),
ANVIL_USE("anvil_use"),
THROW("bow"),
BOWHIT("bowhit1", "bowhit2", "bowhit3", "bowhit4"),
BREAK("break"),
CHESTCLOSED("chestclosed"),
CHESTOPEN("chestopen"),
CLICK("click"),
DOOR("door_close", "door_open"),
DRINK("drink"),
EAT("eat1", "eat2", "eat3"),
EXPLODE("explode1", "explode2", "explode3", "explode4"),
EXPLODE_ALT("old_explode"),
FIZZ("fizz"),
FUSE("fuse"),
LEVELUP("levelup"),
ORB("orb"),
POP("pop"),
SPLASH("splash"),
FALL_BIG("fallbig1", "fallbig2"),
FALL_SMALL("fallsmall"),
HIT("hit1", "hit2", "hit3"),
IGNITE("ignite"),
FIRE("fire"),
RAIN("rain1", "rain2", "rain3", "rain4"),
THUNDER("thunder1", "thunder2", "thunder3"),
PISTON_IN("piston_in"),
PISTON_OUT("piston_out"),
CART("minecart_base"),
CART_INSIDE("minecart_inside"),
MOLTEN("molten"),
MOLTEN_POP("magmapop"),
LAVA("lava"),
LAVA_POP("lavapop"),
WATER("water"),
NOTE("note"),
BLAST_SMALL("blast"),
BLAST_SMALL_FAR("blast_far"),
BLAST_LARGE("large_blast"),
BLAST_LARGE_FAR("large_blast_far"),
LAUNCH("launch"),
TWINKLE("twinkle"),
TWINKLE_FAR("twinkle_far"),
PLOP("plop"),
CUT("cut"),
BAT_DEATH("bat_death"),
BAT_HIT("bat_hurt1", "bat_hurt2", "bat_hurt3", "bat_hurt4"),
BAT_IDLE("bat_idle1", "bat_idle2", "bat_idle3", "bat_idle4"),
BAT_TAKEOFF("bat_takeoff"),
CAT_HIT("cat_hitt1", "cat_hitt2", "cat_hitt3"),
CAT_MEOW("cat_meow1", "cat_meow2", "cat_meow3", "cat_meow4"),
CAT_PURREOW("cat_purreow1", "cat_purreow2"),
CHICKEN_HIT("chicken_hurt1", "chicken_hurt2"),
CHICKEN_IDLE("chicken_say1", "chicken_say2", "chicken_say3"),
COW_HIT("cow_hurt1", "cow_hurt2", "cow_hurt3"),
COW_IDLE("cow_say1", "cow_say2", "cow_say3", "cow_say4"),
DRAGON_IDLE("dragon_growl1", "dragon_growl2", "dragon_growl3", "dragon_growl4"),
DRAGON_WINGS("dragon_wings1", "dragon_wings2", "dragon_wings3", "dragon_wings4", "dragon_wings5", "dragon_wings6"),
HORSE_ANGRY("horse_angry"),
HORSE_BREATHE("horse_breathe1", "horse_breathe2", "horse_breathe3"),
HORSE_DEATH("horse_death"),
HORSE_GALLOP("horse_gallop1", "horse_gallop2", "horse_gallop3", "horse_gallop4"),
HORSE_HIT("horse_hit1", "horse_hit2", "horse_hit3", "horse_hit4"),
HORSE_IDLE("horse_idle1", "horse_idle2", "horse_idle3"),
HORSE_JUMP("horse_jump"),
HORSE_LAND("horse_land"),
HORSE_SOFT("horse_soft1", "horse_soft2", "horse_soft3", "horse_soft4", "horse_soft5", "horse_soft6"),
HORSE_WOOD("horse_wood1", "horse_wood2", "horse_wood3", "horse_wood4", "horse_wood5", "horse_wood6"),
PIG_DEATH("pig_death"),
PIG_IDLE("pig_say1", "pig_say2", "pig_say3"),
RABBIT_HIT("rabbit_hurt1", "rabbit_hurt2", "rabbit_hurt3", "rabbit_hurt4"),
RABBIT_IDLE("rabbit_idle1", "rabbit_idle2", "rabbit_idle3", "rabbit_idle4"),
RABBIT_DEATH("rabbit_bunnymurder"),
RABBIT_JUMP("rabbit_hop1", "rabbit_hop2", "rabbit_hop3", "rabbit_hop4"),
SHEEP_IDLE("sheep_say1", "sheep_say2", "sheep_say3"),
WOLF_BARK("wolf_bark1", "wolf_bark2", "wolf_bark3"),
WOLF_DEATH("wolf_death"),
WOLF_GROWL("wolf_growl1", "wolf_growl2", "wolf_growl3"),
WOLF_HURT("wolf_hurt1", "wolf_hurt2", "wolf_hurt3"),
WOLF_PANTING("wolf_panting"),
WOLF_SHAKE("wolf_shake"),
WOLF_WHINE("wolf_whine"),
SLIME_ATTACK("slime_attack1", "slime_attack2"),
SLIME_BIG("slime_big1", "slime_big2", "slime_big3", "slime_big4"),
SLIME_SMALL("slime_small1", "slime_small2", "slime_small3", "slime_small4", "slime_small5");
private static final Random RANDOM = new Random();
private static final byte[] WAV_HDR = "RIFF".getBytes();
private static final byte[] WAV_HDR_FMT = "fmt ".getBytes();
private static final byte[] WAV_HDR_DATA = "data".getBytes();
private static final byte[] WAV_FORMAT = "WAVE".getBytes();
private final String[] sounds;
private final short[][] buffers;
public static void loadSounds() {
int n = 0;
for(SoundEvent entry : SoundEvent.values()) {
for(int z = 0; z < entry.sounds.length; z++) {
String sound = entry.sounds[z];
Log.SOUND.trace("Lade Sound %s", sound);
entry.buffers[z] = readWav("sounds/" + sound + ".wav", 48000, (short)1);
}
}
}
private static int read32(byte[] data, int off) {
int value = 0;
for(int h = 0; h < 4; h++) {
value |= (int)((data[h + off]) & 0xff) << (8*h);
}
return value;
}
private static short read16(byte[] data, int off) {
short value = 0;
for(int h = 0; h < 2; h++) {
value |= (short)((data[h + off]) & 0xff) << (8*h);
}
return value;
}
private static boolean memcmp(byte[] d1, int off, byte[] d2, int size) {
for(int z = 0; z < size; z++) {
if(d1[z + off] != d2[z])
return true;
}
return false;
}
private static int readWavHeader(byte[] data, int samplerate, short channels, short bytes) {
if(memcmp(data, 0, WAV_HDR, 4)) {
Log.IO.debug("base header");
return 0;
}
int len = read32(data, 4);
if(memcmp(data, 8, WAV_FORMAT, 4)) {
Log.IO.debug("wave header");
return 0;
}
if(memcmp(data, 12, WAV_HDR_FMT, 4)) {
Log.IO.debug("fmt header");
return 0;
}
if(read32(data, 16) != 16) {
Log.IO.debug("header size");
return 0;
}
if(read16(data, 20) != 1) {
Log.IO.debug("pcm");
return 0;
}
if(read16(data, 22) != channels) {
Log.IO.debug("channels");
return 0;
}
if(read32(data, 24) != samplerate) {
Log.IO.debug("sample rate");
return 0;
}
if(read32(data, 28) != (samplerate * ((int)channels) * ((int)bytes))) {
Log.IO.debug("bitrate");
return 0;
}
if(read16(data, 32) != (channels * bytes)) {
Log.IO.debug("sample align");
return 0;
}
if(read16(data, 34) != (8 * bytes)) {
Log.IO.debug("sample size");
return 0;
}
return len;
}
private static short[] readWav(String filename, int samplerate, short channels) {
try {
InputStream fd = new BufferedInputStream(FileUtils.getResource(filename));
byte[] hdr = new byte[36];
if(fd.read(hdr, 0, 36) != 36) {
Log.IO.error("Fehler beim Lesen von WAV-Datei '%s': E/A-Fehler", filename);
fd.close();
return null;
}
if(readWavHeader(hdr, samplerate, channels, (short)2) == 0) {
Log.IO.error("Fehler beim Lesen von WAV-Datei '%s': Falsches oder fehlerhaftes Format", filename);
fd.close();
return null;
}
int len = 0;
do {
if(len != 0 && fd.skip(len) != len) {
Log.IO.error("Fehler beim Lesen von WAV-Datei '%s': E/A-Fehler", filename);
fd.close();
return null;
}
if(fd.read(hdr, 0, 8) != 8) {
Log.IO.error("Fehler beim Lesen von WAV-Datei '%s': E/A-Fehler", filename);
fd.close();
return null;
}
len = read32(hdr, 4);
}
while(memcmp(hdr, 0, WAV_HDR_DATA, 4));
int samples = len / ((int)channels * 2);
byte[] buf = new byte[samples * channels * 2];
if(fd.read(buf, 0, samples * channels * 2) != samples * channels * 2) {
Log.IO.error("Fehler beim Lesen von WAV-Datei '%s': E/A-Fehler", filename);
fd.close();
return null;
}
fd.close();
short[] sbuf = new short[samples * channels];
for(int z = 0; z < samples * channels; z++) {
sbuf[z] = read16(buf, z << 1);
}
return sbuf;
}
catch(FileNotFoundException e) {
Log.IO.error("Fehler beim Öffnen von WAV-Datei '%s': Datei nicht gefunden", filename);
}
catch(IOException e) {
Log.IO.error("Fehler beim Öffnen von WAV-Datei '%s': %s", filename, e.getMessage());
}
return null;
}
private SoundEvent(String ... sounds) {
this.sounds = sounds;
this.buffers = new short[sounds.length][];
}
public short[] getBuffer() {
return RANDOM.pick(this.buffers);
}
}