22 package com.realtime.crossfire.jxclient.sound;
24 import java.io.IOException;
25 import javax.sound.sampled.AudioFormat;
26 import javax.sound.sampled.AudioFormat.Encoding;
27 import javax.sound.sampled.AudioInputStream;
28 import javax.sound.sampled.AudioSystem;
29 import javax.sound.sampled.LineUnavailableException;
30 import javax.sound.sampled.SourceDataLine;
31 import javax.sound.sampled.UnsupportedAudioFileException;
32 import org.jetbrains.annotations.NotNull;
91 state = fadeOut ? 2 : 4;
102 final SourceDataLine sourceDataLine = AudioSystem.getSourceDataLine(audioInputStream.getFormat());
103 final AudioFormat audioFormat = sourceDataLine.getFormat();
105 if (audioFormat.getChannels() > 2) {
106 System.err.println(
"music "+name+
": cannot handle more than two channels");
109 if (audioFormat.getEncoding() != Encoding.PCM_SIGNED) {
110 System.err.println(
"music "+name+
": encoding must be PCM_SIGNED");
113 if (audioFormat.getSampleSizeInBits() != 16) {
114 System.err.println(
"music "+name+
": sample size must be 16 bits");
117 if (audioFormat.isBigEndian()) {
118 System.err.println(
"music "+name+
": cannot handle little endian encoding");
122 sourceDataLine.open(audioInputStream.getFormat());
124 sourceDataLine.start();
126 final byte[] buf =
new byte[8192];
127 while (state < 3 && !Thread.currentThread().isInterrupted()) {
128 int len = audioInputStream.read(buf, 0, buf.length);
131 if (!newAudioInputStream.getFormat().matches(audioInputStream.getFormat())) {
132 newAudioInputStream.close();
133 System.err.println(
"music "+name+
": file format has changed");
136 final AudioInputStream oldAudioInputStream = audioInputStream;
137 audioInputStream = newAudioInputStream;
138 oldAudioInputStream.close();
139 len = audioInputStream.read(buf, 0, buf.length);
141 System.err.println(
"music "+name+
": cannot re-read file");
148 for (
int i = 0; i+3 < len; i += 4) {
150 if (volume >= 1.0F) {
165 for (
int i = 0; i+3 < len; i += 4) {
167 if (volume <= MIN_VALUE) {
179 throw new AssertionError();
182 sourceDataLine.write(buf, 0, len);
185 sourceDataLine.drain();
188 sourceDataLine.stop();
191 sourceDataLine.close();
194 audioInputStream.close();
196 }
catch (
final IOException|LineUnavailableException|UnsupportedAudioFileException ex) {
197 System.err.println(
"music "+name+
": "+ex.getMessage());
207 final float value = (short)((buf[i]&0xFF)+(buf[i+1]&0xFF)*0x100)*
volume;
208 final short s = (short)value;
211 buf[i+1] = (byte)(s/0x100);
214 buf[i+1] = (byte)((s+0x10000)/0x100);
226 return AudioSystem.getAudioInputStream(audioFileLoader.
getInputStream(null, name));
AudioInputStream openAudioInputStream()
Opens and returns an audio stream for name.
final String name
The name of the music to play.
static final float VOLUME_STEP_PER_SAMPLE
The step for the fading in/out factor.
void convertSample(@NotNull final byte[] buf, final int i)
Converts one audio sample according to the current volume.
Processor(@NotNull final String name, @NotNull final AudioFileLoader audioFileLoader)
Creates a new instance.
A thread that plays a music file over and over until terminated.
int state
The current state: 0=fade in, 1=playing, 2=fade out, 3=terminate, 4=terminate immediately.
InputStream getInputStream(@Nullable final String name, @NotNull final String action)
Returns an input stream for an audio file.
void terminate(final boolean fadeOut)
Stops playing music.
float volume
The current volume.
final AudioFileLoader audioFileLoader
The AudioFileLoader for loading audio files.
static final float MIN_VALUE
The minimum factor for fading in/out effects.