package sound; import util.settings.Settings; import javax.sound.sampled.*; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; /** * Represents a sound with its source and use counter. * * @author Dr. Kegel */ public class SoundEntry implements Closeable { private final File key; private SoundEntry previous; private final AudioInputStream source; private final Clip clip; /** * Instantiates a new {@link SoundEntry} based on a file. * * @param file The sound file. * @throws java.io.IOException */ public SoundEntry(File file, SoundEntry previous, ConcurrentHashMap<File, SoundEntry> map) throws IOException { try { key = file; source = AudioSystem.getAudioInputStream(file); this.previous = previous; DataLine.Info info = new DataLine.Info(Clip.class, source.getFormat()); clip = (Clip) AudioSystem.getLine(info); clip.addLineListener(new Closer(this, map)); clip.open(source); } catch (UnsupportedAudioFileException | LineUnavailableException e) { throw new IOException(e); } //sector.incrementAndGet(); TODO look into implementing a counter for how many of each sound is played } @Override public void close() { if (clip.isActive()) { clip.stop(); } if (clip.isOpen()) { clip.flush(); clip.drain(); clip.close(); } try { source.close(); } catch (Exception ignored) { } // secl.incrementAndGet(); TODO count if (previous != null) { previous.close(); previous = null; } } /** * Returns the audio clip. * * @return the audio clip. */ public Clip getClip() { return this.clip; } /** * Returns the file. * * @return the file. */ public File getKey() { return this.key; } /** * Plays this sound. * * @param mode Strategy for handling the case that the sound is already playing. */ public void play(final SoundPlayer.PlayMode mode) { if (this.clip.isRunning()) { switch (mode) { case Ignore: return; case Restart: this.stop(); break; case Toggle: this.stop(); return; default: break; } } else { this.clip.setFramePosition(0); } FloatControl volume = (FloatControl) this.clip.getControl(FloatControl.Type.MASTER_GAIN); /** @author Chrisazy * I've decided that -75.0 is what qualifies as silent, so that's our baseline * We need to counter the logarithmic nature of gain, so we use Pow with base 10 * We use it on 100 - volume setting because we're actually considering 0 gain to be 100% * and -75.0 gain to be 0% * We subtract by 1 because we want Math.Pow(10,(100-100)) to be 0, instead of 1. * Lastly, we normalize our gain by multiplying by our "silent" level divided by the actual 0% level * (Since without the normalization at 0% we get a gain of -9, that's out 0% level) * Shit's so cash. */ float vol = -((75F / 9F) * (float) (Math.pow(10, ((100 - Settings.soundVolumeGain.getValue()) / 100)) - 1)); volume.setValue(vol); this.clip.start(); //sepl.incrementAndGet(); TODO counter } /** * Stops this sound. */ public void stop() { this.clip.stop(); this.clip.flush(); this.clip.setFramePosition(0); } }