package game.init; import java.io.BufferedInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import game.FileUtils; import game.Log; import game.rng.Random; 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); } }