I'm developing a game in Java, and have made an attempt at coding a simple sound system for it made of two class files: one that handles them, and one for each sound file loaded.
My problem is that every once in a while I get a huge lagspike which means a complete stop for like a second or two, really interrupting gameplay. I'm suspecting Garbage control but I'm not entirely sure. The only thing I know for a fact is that the source of the problem lies in the sounds.
Here's my SoundHandler.java:
(The loading of sounds is unimportant, as far as I know it should be unrelated to the problem)
package Classes;
import java.io.*;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.FloatControl;
public class SoundHandler {
Sound Sounds[] = new Sound[1];
public SoundHandler()
{
if(!LoadSounds("Sounds.cfg"))
System.out.print("Failiure upon loading sounds!");
}
public boolean LoadSounds(String FileName)
{
String line = "";
String SoundName = "";
String SoundFile = "";
String[] token3 = new String[10];
boolean EndOfFile = false;
int LineCount = 0;
BufferedReader characterfile = null;
try
{
characterfile = new BufferedReader(new FileReader(GameMain.GameFolder+"Data/"+FileName));
}
catch(FileNotFoundException fileex)
{
System.out.println(FileName+": file not found.");
return false;
}
while(!EndOfFile && line != null)
{
try
{
line = characterfile.readLine();
if(line != null)
{
if(line.indexOf("//") == -1 && !line.equals(""))
LineCount++;
}
}
catch(IOException ioexception)
{
if(LineCount == 0)
{
System.out.println(FileName+": error loading file.");
return false;
}
EndOfFile = true;
}
}
try { characterfile.close(); } catch(IOException ioexception) { characterfile = null; }
Sounds = new Sound[LineCount];
EndOfFile = false;
LineCount = 0;
try
{
characterfile = new BufferedReader(new FileReader(GameMain.GameFolder+"Data/"+FileName));
}
catch(FileNotFoundException fileex)
{
System.out.println(FileName+": file not found.");
return false;
}
try
{
line = characterfile.readLine();
if(line != null)
if(line.indexOf("//") == -1 && !line.equals(""))
LineCount++;
}
catch(IOException ioexception) { }
while(EndOfFile == false && line != null) {
if(line.indexOf("//") == -1 && !line.equals(""))
{
line = line.trim();
line = line.replaceAll("\t\t", "\t");
line = line.replaceAll("\t\t", "\t");
line = line.replaceAll("\t\t", "\t");
line = line.replaceAll("\t\t", "\t");
int Spot = line.indexOf("\t");
SoundName = line.substring(0,Spot);
SoundFile = line.substring(Spot+1);
Sounds[LineCount-1] = new Sound(SoundName,SoundFile);
}
try {
line = characterfile.readLine();
if(line != null)
if(line.indexOf("//") == -1 && !line.equals(""))
LineCount++;
} catch(IOException ioexception1) { EndOfFile = true; }
}
try { characterfile.close(); } catch(IOException ioexception) { }
return true;
}
public File GetSoundFile(String Name)
{
File result = null;
for(int i = 0; i < Sounds.length; i++)
if(Sounds[i].Name.equals(Name))
result = Sounds[i].File;
return result;
}
public Sound GetSound(String Name)
{
Sound result = null;
for(int i = 0; i < Sounds.length; i++)
if(Sounds[i].Name.equals(Name))
result = Sounds[i];
return result;
}
public int GetSoundID(String Name)
{
int result = 0;
for(int i = 0; i < Sounds.length; i++)
if(Sounds[i].Name.equals(Name))
result = i;
return result;
}
Double MasterVolume = 0.75;
public float CalcVolume(double Vol)
{
float result = 0f;
result = -40.0f + (float)(MasterVolume*Vol*40);
if(result < -40.0f)
result = -40.0f;
if(result > 0.0f)
result = 0.0f;
return result;
}
public boolean PlaySound(String SoundName, double Vol)
{
int ID = GetSoundID(SoundName);
try
{
Clip CurrentClip;
Sounds[ID].Reset(false);
CurrentClip = (Clip) AudioSystem.getLine(Sounds[ID].info);
CurrentClip.addLineListener(new LineListener() {
public void update(LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
event.getLine().close();
}
}
});
CurrentClip.open(Sounds[ID].sound);
FloatControl Volume;
Volume = (FloatControl) CurrentClip.getControl(FloatControl.Type.MASTER_GAIN);
Volume.setValue(CalcVolume(Vol));
CurrentClip.start();
}
catch(LineUnavailableException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
return true;
}
}
Here's my Sound.java:
package Classes;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
public class Sound {
public String Name = "";
public File File = null;
AudioInputStream sound;
DataLine.Info info;
Clip clip;
public Sound(String iName, String FileName)
{
Name = iName;
File = new File(GameMain.GameFolder+"Sound/"+FileName+".wav");
Reset(true);
}
public void Reset(boolean init)
{
try
{
if(!init)
sound.close();
sound = AudioSystem.getAudioInputStream(File);
info = new DataLine.Info(Clip.class, sound.getFormat());
}
catch(IOException e) { e.printStackTrace(); }
catch(UnsupportedAudioFileException e) { e.printStackTrace(); }
}
}
I've tried searching around for a general way to implement sounds in a game, most I've encountered didn't feature multiple instances of the same sound file running at once, this is what I have so far. I'm sure there are a few tiny inefficiencies especially in the loading code, but there's got to be some leak I'm missing. Any tips for custom GC usage are also welcome.
Thanks in advance.
It might be easier to research concurrent threading on the Java Oracle site... I can get a link. There are ways to sync threads together and they do have examples.
Oracle Concurrency Documenation! ->> Object Syncing
Related
Screenshot of program running (top left: server, the rest are clients):
In the bottom-right window, I am trying to press Control D (mac) (for windows it's control Z) in order to exit the bottom right window/client alone without exiting the entire application/program but it doesn't seem to be working because I can still type "it didn't work" and it outputs the message.
My question is: What changes can I make to the following code so that when a client presses Control D it will close just one window/client and not exit the whole application?
Part of code that should close the window (currently empty):
//This is the code that prints messages to all clients
synchronized (this)
{
for (int i = 0; i < maxClientsCount; i++)
{
if (!line.equals(null) && !line.equals("null") && !line.equals(null) && !line.equals("F") && !line.equals("m") && !line.equals("M") && threads[i] != null && threads[i].clientName != null && !threads[i].clientName.equals("m") && !threads[i].clientName.equals("M"))
{
if(!line.equals("") == true && line.isEmpty()== false)
{
threads[i].os.println(name + ": " + line);
}
}
//After Control D/Z is pressed, this code will execute
else if(line.equals(null) || line.equals("null") || line.contains("null"))
{
try
{
//This code location exits the program, system.exit(0) and system.exit(-1) didn't work
//how do i close only one client window here without exiting the whole program?
}
catch (NullPointerException ignored)
{
}
finally
{
}
// threads[i].os.close();
// System.exit(0);
}
}
}
NOTE: SKIP THE REST and scroll down if you already know the answer
Full code of ClientThreads.java:
import java.io.*;
import java.net.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.nio.*;
import java.nio.channels.FileChannel;
class ClientThreads extends Thread
{
public String path = "";
public String name1 = "";
private String clientName = null;
private DataInputStream is = null;
private PrintStream os = null;
private Socket clientSocket = null;
private final ClientThreads[] threads;
private int maxClientsCount;
public int position = 0;
public static List<String> listName = Collections.synchronizedList(new ArrayList<String>());
List<String> l = Collections.synchronizedList(new ArrayList<String>());
public String[] namesList = new String[10];
public ClientThreads(Socket clientSocket, ClientThreads[] threads,
String name, String[] namesList, List<String> listName)
{
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
this.name1 = name;
this.namesList = namesList;
}
#SuppressWarnings("deprecation")
public void run()
{
int maxClientsCount = this.maxClientsCount;
ClientThreads[] threads = this.threads;
synchronized (listName)
{
//Iterator i = listName.iterator(); // Must be in synchronized block
ListIterator<String> i = listName.listIterator();
}
try
{
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
String name;
String name3;
while (true)
{
//os.println("What is your name?");
name = is.readLine().trim();
name3 = name;
break;
}
synchronized(listName)
{
if(!listName.contains(name))
{
if(!listName.contains(name) && name != null && !name.isEmpty())
{
listName.add(name);
Path currentRelativePath = Paths.get("");
path = currentRelativePath.toAbsolutePath().toString();
}
}
}
synchronized (this)
{
for (int i = 0; i < maxClientsCount; i++)
{
if (threads[i] != null && threads[i] == this)
{
clientName = "#" + name;
break;
}
}
for (int i = 0; i < maxClientsCount; i++)
{
if (threads[i] != null)
{
}
}
}
while (true)
{
synchronized(listName)
{
}
String line = is.readLine();
if (line.contains("3582938758912781739713asfaiwef;owjouruuzlxjcjnbbiewruwoerpqKFDJiuxo9"))
{
break;
}
else
{
}
synchronized (this)
{
for (int i = 0; i < maxClientsCount; i++)
{
if (!line.equals(null) && !line.equals("null") && !line.equals(null) && !line.equals("F") && !line.equals("m") && !line.equals("M") && threads[i] != null && threads[i].clientName != null && !threads[i].clientName.equals("m") && !threads[i].clientName.equals("M"))
{
if(!line.equals("") == true && line.isEmpty()== false)
{
threads[i].os.println(name + ": " + line);
}
}
else if(line.equals(null) || line.equals("null") || line.contains("null"))
{
try
{
//This code location exits the program, system.exit(0) and system.exit(-1) didn't work
//how do i close only one client window here without exiting the whole program?
}
catch (NullPointerException ignored)
{
}
finally
{
}
// threads[i].os.close();
// System.exit(0);
}
}
}
// }
}
synchronized (this)
{
for (int i = 0; i < maxClientsCount; i++)
{
if (threads[i] != null && threads[i] != this && threads[i].clientName != null)
{
// threads[i].os.println(name + "has disconnected.");
threads[i].listName.remove(name);
listName.remove(name);
// threads[i].os.println("The list now contains: " + listName);
// System.out.println("A user disconnected. The list now contains: " +listName);
}
}
}
synchronized (this)
{
for (int i = 0; i < maxClientsCount; i++)
{
if (threads[i] == this)
{
//threads[i] = null;
}
}
}
// is.close();
// os.close();
//clientSocket.close();
}
catch (IOException e)
{
}
}
}
Full code of ChatClient.java:
import java.io.*;
import java.net.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ChatClient implements Runnable
{
public static String path = "";
private static Socket clientSocket = null;
private static PrintStream os = null;
private static DataInputStream is = null;
private static BufferedReader inputLine = null;
private static boolean closed = false;
public static String[] namesList = new String[10];
public int iteration = 0;
public static String[] responses = new String[50];
public int responseCount = 0;
public static final int maxClientsCount = 10;
public static final ClientThreads[] threads = new ClientThreads[maxClientsCount];
public static List<String> listName = Collections.synchronizedList(new ArrayList<String>());
List<String> l = Collections.synchronizedList(new ArrayList<String>());
public ChatClient()
{
}
public static void main(String[] args)
{
for(int i = 0; i < namesList.length; i++)
{
namesList[i] = "";
}
for(int j = 0; j < responses.length; j++)
{
responses[j] = "";
}
// System.out.println("args[0] is: " + args[0]);
int portNumber = Integer.valueOf(args[0]);
String host = "localhost";
//int filePort = Integer.valueOf(args[0]);
try
{
synchronized(listName)
{
clientSocket = new Socket(host, portNumber);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
is = new DataInputStream(clientSocket.getInputStream());
}
}
catch (UnknownHostException e)
{
//System.err.println("Don't know about host " + host);
} catch (IOException e)
{
// System.err.println("Couldn't get I/O for the connection to the host "
// + host);
}
if (clientSocket != null && os != null && is != null)
{
try
{
new Thread(new ChatClient()).start();
while (!closed)
{
os.println(inputLine.readLine() );
}
// os.close();
//is.close();
//clientSocket.close();
}
catch (IOException e)
{
// System.err.println("IOException: " + e);
}
}
}
#SuppressWarnings("deprecation")
public void run()
{
String responseLine = "";
try
{
while ((responseLine = is.readLine()) != null)
{
if(responseLine!=null && !responseLine.equals(null) && responseLine!="null" && !responseLine.equals("null") && !responseLine.contains("null"))
{
System.out.println(responseLine);
}
else if(responseLine.contains("null") || responseLine.equals("null") || responseLine==null || responseLine.equals(null))
{
//This is another location which will be executed if Control D/Control Z is pressed
//os.close();
// is.close();
//System.exit(0);
}
}
//closed = true;
}
catch (IOException e)
{
// System.err.println("IOException: " + e);
}
}
}
Full code of ChatServer.java:
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer
{
public static List<String> listName = Collections.synchronizedList(new ArrayList<String>());
List<String> l = Collections.synchronizedList(new ArrayList<String>());
public static ServerSocket serverSocket = null;
public static Socket clientSocket = null;
public static final int maxClientsCount = 10;
public static final ClientThreads[] threads = new ClientThreads[maxClientsCount];
public static String[] namesList = new String[10];
// public ChatClient arrayOfNames = new ChatClient;
public static void main(String args[])
{
synchronized (listName)
{
//Iterator i = listName.iterator(); // Must be in synchronized block
Iterator<String> i = listName.listIterator();
}
int once = 0;
if(once == 0)
{
// System.out.println("args[0] is: " + args[0]);
int portNumber = Integer.valueOf(args[0]);
// System.out.println("waiting for connections on port " + portNumber + " ...\n ");
once = 3;
}
once = 3;
try
{
int portNumber1 = Integer.valueOf(args[0]);
serverSocket = new ServerSocket(portNumber1);
}
catch (IOException e)
{
System.out.println(e);
}
while (true)
{
try
{
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++)
{
if (threads[i] == null)
{
String name = "";
(threads[i] = new ClientThreads(clientSocket, threads, name, namesList, listName)).start();
break;
}
}
if (i == maxClientsCount)
{
//PrintStream os = new PrintStream(clientSocket.getOutputStream());
// os.println("Server too busy. Try later.");
// os.close();
// clientSocket.close();
}
}
catch (IOException e)
{
System.out.println(e);
}
}
}
}
EDIT: it might also be possible to change threads[i] to threads[i+1] in order to keep track of different clients in certain parts of the code
What you need instead of this:
while (!closed)
{
os.println(inputLine.readLine() );
}
is this:
String line;
while ((line = inputLine.readLine()) != null)
{
os.println(line);
}
This will fall-through when ctrl/d or ctrl/z is pressed, as appropriate, and main() will then exit. Provided you have also made your threads daemons, the JVM will then exit.
NB this:
// After Control D/Z is pressed, this code will execute
isn't true, and this:
else if(line.equals(null) || line.equals("null") || line.contains("null"))
is drivel. line.equals(null) can never be true, by definition, otherwise a NullPointerException would have been thrown instead of calling .equals(): and why you should be interested in whether the user has typed "null", or something containing "null", is a mystery.
And why you are using synchronized(listName) in the main() method of an application which up to this point is single-threaded is another mystery.
I have a very specific problem with JLayer in my Music-Player project. I want to include something to adjust the volume, but it seems it isn't that easy to implement.
This is because JLayer isn't supporting it from itself. I excluded the Player class from my project and changed some methods and it works fine for playing mp3. For adjusting the volume I added to the Player class this method:
public boolean setGain(float newGain) {
if (audio instanceof JavaSoundAudioDevice) {
System.out.println("InstanceOf");
JavaSoundAudioDevice jsAudio = (JavaSoundAudioDevice) audio;
try {
jsAudio.write(null, 0, 0);
} catch (JavaLayerException ex) {
ex.printStackTrace();
}
return jsAudio.setLineGain(newGain);
}
return false;
}
I then extracted the JavaSoundAudioDevice, decompiled it and changed it:
public boolean setLineGain(float gain)
{
System.out.println("Vor Source");
if (source != null)
{
System.out.println("Nach Source");
FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());
volControl.setValue(newGain);
return true;
}
return false;
}
And:
public void createSource() throws JavaLayerException {
Throwable t = null;
try {
Line line = AudioSystem.getLine(getSourceLineInfo());
if (line instanceof SourceDataLine) {
source = (SourceDataLine) line;
//source.open(fmt, millisecondsToBytes(fmt, 2000));
source.open(fmt);
/*
if (source.isControlSupported(FloatControl.Type.MASTER_GAIN))
{
FloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN);
c.setValue(c.getMaximum());
}*/
source.start();
}
} catch (RuntimeException ex) {
t = ex;
} catch (LinkageError ex) {
t = ex;
} catch (LineUnavailableException ex) {
t = ex;
}
if (source == null) {
throw new JavaLayerException("cannot obtain source audio line", t);
}
}
But the createSource method, which was already implemented, doesn't work. At the line
Line line = AudioSystem.getLine(getSourceLineInfo());
I always get an IllegalArgumentException:
java.lang.IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_SIGNED 0.0 Hz, 16 bit, 0 channels, 0 bytes/frame, little-endian is supported.
at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:479)
at javazoom.jl.player.JavaSoundAudioDevice.createSource(JavaSoundAudioDevice.java:80)
at javazoom.jl.player.JavaSoundAudioDevice.writeImpl(JavaSoundAudioDevice.java:119)
at javazoom.jl.player.AudioDeviceBase.write(Unknown Source)
at MusikPlayer.Erweiterungen.Players.MyPlayer.setGain(MyPlayer.java:192)
at MusikPlayer.PlayerTest.main(PlayerTest.java:21)
Exception in thread "main" java.lang.IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_SIGNED 0.0 Hz, 16 bit, 0 channels, 0 bytes/frame, little-endian is supported.
at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:479)
at javazoom.jl.player.JavaSoundAudioDevice.createSource(JavaSoundAudioDevice.java:80)
at javazoom.jl.player.JavaSoundAudioDevice.writeImpl(JavaSoundAudioDevice.java:119)
at javazoom.jl.player.AudioDeviceBase.write(Unknown Source)
at MusikPlayer.Erweiterungen.Players.MyPlayer.decodeFrame(MyPlayer.java:161)
at MusikPlayer.Erweiterungen.Players.MyPlayer.play(MyPlayer.java:87)
at MusikPlayer.Erweiterungen.Players.MyPlayer.play(MyPlayer.java:66)
at MusikPlayer.PlayerTest.main(PlayerTest.java:22)
Does anyone know why this is happening? Does anyone know how to solve this issue?
Well, i solved it..
This Test class is used:
public class PlayerTest {
public static void main(String[] args) {
try {
File f = new File("D:\\Musik\\Musik-Oberordner\\Favoriten\\06-ich_und_ich_-_so_soll_es_bleiben.mp3");
MyPlayer player = new MyPlayer(new FileInputStream(f));
player.setGain(-30f);
player.play();
} catch (JavaLayerException | FileNotFoundException ex) {
ex.printStackTrace();
}
}
the setten Gain will adjust the volume, from -80.0f to 6f.
The changed JavaSoundAudioDevice:
package javazoom.jl.player;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.JavaLayerException;
/**
* The <code>JavaSoundAudioDevice</code> implements an audio device by using the
* JavaSound API.
*
* #since 0.0.8
* #author Mat McGowan
*/
public class JavaSoundAudioDevice extends AudioDeviceBase {
private SourceDataLine source = null;
private AudioFormat fmt = null;
private byte[] byteBuf = new byte[4096];
protected void setAudioFormat(AudioFormat fmt0) {
fmt = fmt0;
}
protected AudioFormat getAudioFormat() {
// if (fmt == null) {
fmt = new AudioFormat(44100,
16,
2,
true,
false);
return fmt;
}
protected DataLine.Info getSourceLineInfo() {
AudioFormat fmt = getAudioFormat();
//DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt, 4000);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt);
return info;
}
public void open(AudioFormat fmt) throws JavaLayerException {
if (!isOpen()) {
setAudioFormat(fmt);
openImpl();
setOpen(true);
}
}
public boolean setLineGain(float gain) {
System.out.println("Vor Source");
if (source != null) {
System.out.println("Nach Source");
FloatControl volControl = (FloatControl) source.getControl(FloatControl.Type.MASTER_GAIN);
float newGain = Math.min(Math.max(gain, volControl.getMinimum()), volControl.getMaximum());
volControl.setValue(newGain);
return true;
}
return false;
}
public void openImpl()
throws JavaLayerException {
}
// createSource fix.
public void createSource() throws JavaLayerException {
Throwable t = null;
try {
Line line = AudioSystem.getLine(getSourceLineInfo());
if (line instanceof SourceDataLine) {
source = (SourceDataLine) line;
//source.open(fmt, millisecondsToBytes(fmt, 2000));
source.open(fmt);
// if (source.isControlSupported(FloatControl.Type.MASTER_GAIN))
// {
// System.out.println("Control");
// FloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN);
// c.setValue(c.getMinimum());
// }
source.start();
}
} catch (RuntimeException ex) {
t = ex;
} catch (LinkageError ex) {
t = ex;
} catch (LineUnavailableException ex) {
t = ex;
}
if (source == null) {
throw new JavaLayerException("cannot obtain source audio line", t);
}
}
public int millisecondsToBytes(AudioFormat fmt, int time) {
return (int) (time * (fmt.getSampleRate() * fmt.getChannels() * fmt.getSampleSizeInBits()) / 8000.0);
}
protected void closeImpl() {
if (source != null) {
source.close();
}
}
protected void writeImpl(short[] samples, int offs, int len)
throws JavaLayerException {
if (source == null) {
createSource();
}
byte[] b = toByteArray(samples, offs, len);
source.write(b, 0, len * 2);
}
protected byte[] getByteArray(int length) {
if (byteBuf.length < length) {
byteBuf = new byte[length + 1024];
}
return byteBuf;
}
protected byte[] toByteArray(short[] samples, int offs, int len) {
byte[] b = getByteArray(len * 2);
int idx = 0;
short s;
while (len-- > 0) {
s = samples[offs++];
b[idx++] = (byte) s;
b[idx++] = (byte) (s >>> 8);
}
return b;
}
protected void flushImpl() {
if (source != null) {
source.drain();
}
}
public int getPosition() {
int pos = 0;
if (source != null) {
pos = (int) (source.getMicrosecondPosition() / 1000);
}
return pos;
}
/**
* Runs a short test by playing a short silent sound.
*/
public void test()
throws JavaLayerException {
// try {
open(new AudioFormat(22000, 16, 1, true, false));
short[] data = new short[22000 / 10];
write(data, 0, data.length);
flush();
close();
// } catch (RuntimeException ex) {
// throw new JavaLayerException("Device test failed: " + ex);
// }
}
}
Now u have to just implement it into ur Project, overwrite the old JavaSoundDevice and enjoy VolumeAdjusting!
I have my java file set up to calculate a phone bill and print out to the console in this format.
Invoice
--------------------------
Account Amount Due
10011 $12.25
10033 $11.70
--------------------------
Total $23.95
but when I run the program I only get this on the text file
Account Amount_Due
10011 $12.25
10033 $11.7
Can someone help me edit my filecreating code in correct format?
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Vector;
public class PhoneBill {
Vector data;
Vector processed = new Vector();
Vector markProcessed = new Vector();
public void readFile(String inFileStr)
{
String str = "";
data = new Vector<LineItem>();
FileReader fReader;
InputStream inFileStream;
try{
fReader = new FileReader(inFileStr);
BufferedReader br=new BufferedReader(fReader);
String line;
while ((line=br.readLine())!= null){
if (line.indexOf("_") != -1)
continue;
else
if (!line.isEmpty()){
data.add(new LineItem(line.trim()));
}
}
br.close();
}
catch (Exception e){
}
}
public void processCharges()
{
String out = "Account Amount_Due\n";
System.out.println ("Invoice");
System.out.println ("--------------------------");
System.out.println ("Account " + "Amount Due ");
double total = 0.0;
double lCharges =0;
boolean done = false;
DecimalFormat numFormatter = new DecimalFormat("$##.##");
for (int j = 0; j < data.size(); j++ ){
LineItem li = (LineItem)data.get(j);
String accNum = li.getAccountNum();
if (j > 0){
done = checkProcessed(accNum);}
else
processed.add(accNum);
if (!done){
lCharges = 0;
for (int i = 0; i < data.size(); i++){
String acc = ((LineItem)data.get(i)).getAccountNum();
if (acc.equals(accNum) && !done)
lCharges += processItemCharges(accNum);
done = checkProcessed(accNum);
}
lCharges+=10.0;
System.out.format ("%s" + " $%.2f%n",accNum, lCharges);
out += accNum+" ";
out += numFormatter.format(lCharges)+"\n";
processed.add(accNum);
total += lCharges;
}
}
System.out.println ("--------------------------");
System.out.format ("%s" + " $%.2f%n","Total", total);
writeToFile("invoice.txt", out);
}
private void writeToFile(String filename,String outStr)
{
try{
File file = new File(filename);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(outStr);
bw.close();
} catch (IOException ioe){
System.out.println(ioe.getMessage());
}
}
private boolean checkProcessed(String accNum){
if (processed.contains(accNum))
return true;
else
return false;
}
private double processItemCharges(String accNum)
{
double charges = 0.0;
for (int i = 0; i < data.size(); i++)
{
if(((LineItem)data.get(i)).getAccountNum().equals(accNum))
charges += ((LineItem)data.get(i)).getCharges();
}
return charges;
}
public static void main(String[] args)
{
PhoneBill pB = new PhoneBill();
pB.readFile("input_data.txt");
pB.processCharges();
}
class LineItem{
String accNum ;
String timeOfCall;
double mins;
double amountDue;
boolean counted = false;
public LineItem(String accStr)
{
processAccount(accStr);
}
private void processAccount(String accStr){
StringTokenizer st = new StringTokenizer(accStr);
accNum = (String)st.nextElement();
timeOfCall = (String) st.nextElement();
mins = Double.parseDouble((String) st.nextElement());
if (timeOfCall.compareTo("08:00")>0 && timeOfCall.compareTo("22:00")<0)
amountDue = mins*0.10;
else
amountDue = mins*0.05;
}
public String getAccountNum()
{
return accNum;
}
public double getCharges()
{
return amountDue;
}
}
}
Study this. It uses a bit more advanced Java but understanding it will be well worth your while.
package test;
import java.io.*;
import java.util.*;
public class PhoneBill {
private static String BILL_FORMAT = "%-10s $%,6.2f\n";
private static boolean DEBUG=true;
Map<String, List<LineItem>> accounts = new HashMap<String,List<LineItem>>();
public void readFile(String inFileStr) {
FileReader fReader=null;
try {
fReader = new FileReader(inFileStr);
BufferedReader br = new BufferedReader(fReader);
String line;
while ((line = br.readLine()) != null) {
if (line.indexOf("_") != -1)
continue;
else if (!line.isEmpty()) {
LineItem li = new LineItem(line.trim());
List<LineItem> list = accounts.get(li.accNum);
if(list==null){
list = new ArrayList<LineItem>();
accounts.put(li.accNum, list);
}
list.add(li);
}
}
br.close();
} catch (Exception e) {
/* Don't just swallow Exceptions. */
e.printStackTrace();
} finally {
if(fReader!=null){
try{
fReader.close();
} catch(Exception e){
e.printStackTrace();
}
}
}
}
public void processCharges() {
StringBuffer out = new StringBuffer(100)
.append("Invoice\n")
.append("--------------------------\n")
.append("Account Amount Due \n");
double total = 0.0;
double lCharges = 0;
for (String accNum:accounts.keySet()) {
List<LineItem> account = accounts.get(accNum);
lCharges = 10;
for(LineItem li:account){
lCharges += li.getCharges();
}
total += lCharges;
out.append(String.format(BILL_FORMAT, accNum, lCharges));
}
out.append("--------------------------\n");
out.append(String.format(BILL_FORMAT, "Total", total));
writeToFile("invoice.txt", out.toString());
}
private void writeToFile(String filename, String outStr) {
if(DEBUG){
System.out.printf("========%swriteToFile:%s=========\n", '=', filename);
System.out.println(outStr);
System.out.printf("========%swriteToFile:%s=========\n", '/', filename);
}
try {
File file = new File(filename);
// If file doesn't exist, then create it.
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(outStr);
bw.close();
} catch (IOException ioe) {
System.out.println(ioe.getMessage());
}
}
public static void main(String[] args) {
PhoneBill pB = new PhoneBill();
pB.readFile("input_data.txt");
pB.processCharges();
}
static class LineItem {
String accNum;
double timeOfCall;
double mins;
double amountDue;
boolean counted = false;
private static final double EIGHT_AM = convertTime("08:00");
private static final double TEN_PM = convertTime("22:00");
public LineItem(String accStr) {
processAccount(accStr);
}
private void processAccount(String accStr) {
StringTokenizer st = new StringTokenizer(accStr);
accNum = st.nextToken();
timeOfCall = convertTime(st.nextToken());
mins = Double.parseDouble(st.nextToken());
if (timeOfCall > EIGHT_AM && timeOfCall < TEN_PM)
amountDue = mins * 0.10;
else
amountDue = mins * 0.05;
}
public String getAccountNum() {
return accNum;
}
public double getCharges() {
return amountDue;
}
private static double convertTime(String in){
/* Will blow up if `in` isn't given in h:m. */
String[] h_m = in.split(":");
return Double.parseDouble(h_m[0])*60+Double.parseDouble(h_m[1]);
}
}
}
Printing to the console (i.e. System.out.println) is not the same as concatenating to your out variable (i.e. out+=).
So when you call
writeToFile("invoice.txt", out);
You are only writing what is in the string 'out' to the file. If you look back at your code, you'll see that all of your missing lines are only ever printed to the console, but not concatenated to the 'out' variable. Correct that and you shouldn't have a problem.
I am creating a metronome program and the for loop is executing +1 times than it should.
public class Tempo {
String file;
int bpm;
public Tempo(int bpm, String file){
this.bpm=bpm;
this.file=file;
}
public void tempoPlay () throws InterruptedException{
new Play(file).start();
Thread.sleep(60000/bpm);
}
public static void main(String[] args) throws InterruptedException {
Tempo t = new Tempo(120, "C:\\Users\\Korisnik\\Desktop\\dome3.wav");
for(int i=0;i<20;i++){
t.tempoPlay();
}
}
}
The first beat is rapidly followed by the second one but later as it goes it is sounding compliant. I've counted it plays 21 beats but it should play 20.
Here's the Play class:
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
class Play extends Thread {
private String filename;
private Position curPosition;
private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb
enum Position {
LEFT, RIGHT, NORMAL
};
public Play(String wavfile) {
filename = wavfile;
curPosition = Position.NORMAL;
}
public Play(String wavfile, Position p) {
filename = wavfile;
curPosition = p;
}
#Override
public void run() {
File soundFile = new File(filename);
if (!soundFile.exists()) {
System.err.println("Wave file not found: " + filename);
return;
}
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline
.getControl(FloatControl.Type.PAN);
if (curPosition == Position.RIGHT) {
pan.setValue(1.0f);
} else if (curPosition == Position.LEFT) {
pan.setValue(-1.0f);
}
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0) {
auline.write(abData, 0, nBytesRead);
}
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
Shot in the dark: It might be worthwhile to read the file into memory completely for testing purposes. A guess as to what might be happening is that the I/O from reading the file is interfering with the timing of the playback.
You might be able to get away with this to test.
Tempo t = new Tempo(120, "C:\\Users\\Korisnik\\Desktop\\dome3.wav");
t.tempoPlay() // ignore this
Thread.sleep(10);
for(int i=0;i<20;i++){
t.tempoPlay();
}
Or better yet, have Tempo cache the read in before playing the sound.
I am learning how to use Java and I want to make a text scroller for my website.
I have found a similar scroller that I want to add but I want to look at the code to see how it was done.
The applet can be found here: http://www.javascriptkit.com/java/java20.shtml
The problem is when I try to open the class file within notepad the encoding or text shows up with strange characters instead of showing me the code.
Please can someone let me know if there is any possible way of me seeing the code for this class.
Thanks
That is a class file meaning it is compiled code so you can not see it's source.
In order to see the source, you need the .java file which is the file which you compile to get the byte code.
It seems the site is just providing the compiled class, and you never know using it they might have some hidden functionality in the class as well e.g to send information to the owner servers etc.
EDIT:
So here is the de-compiled code of applet written by ProScroll version 2.3 by Slava Pestov
import java.applet.Applet;
import java.applet.AppletContext;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
public class ProScroll extends Applet
implements Runnable
{
private Thread thread;
private Image image;
private int scrollLength;
private int scrolled;
private int speed = 10;
private int imgsWidth;
private URL url;
private String target;
private Color bgColor;
public void init()
{
int i = 12; int j = 0;
String str2 = getParameter("TEXT");
String str3 = getParameter("TEXTURL");
if ((str2 == null) && (str3 == null)) {
str2 = "No TEXT or TEXTURL parameter specified";
}
if (str3 != null)
{
localObject = new StringBuffer();
try
{
InputStream localInputStream = new URL(str3)
.openConnection().getInputStream();
while (true)
{
int k = localInputStream.read();
if (k == -1) break;
if (k != 10) {
if (k == 9) { ((StringBuffer)localObject).append(' '); continue; }
((StringBuffer)localObject).append((char)k);
}
}
localInputStream.close();
str2 = ((StringBuffer)localObject).toString();
}
catch (Exception localException1)
{
if (str2 == null) {
str2 = "Error loading text from URL: " + localException1;
}
}
}
String str1 = getParameter("FONT");
if (str1 == null) str1 = "TimesRoman";
this.target = getParameter("TARGET");
if (this.target == null) this.target = "_self";
try
{
i = Integer.parseInt(getParameter("SIZE"));
}
catch (Exception localException2)
{
}
Object localObject = getParameter("STYLE");
if ("bold".equals(localObject)) j = 1;
else if ("italic".equals(localObject)) j = 2;
else if ("bolditalic".equals(localObject)) j = 3;
String str4 = getParameter("SPEED");
if ("slow".equals(str4)) this.speed = 20;
else if ("medium".equals(str4)) this.speed = 15; else {
this.speed = 10;
}
try
{
this.url = new URL(getDocumentBase(), getParameter("URL"));
}
catch (Exception localException3)
{
}
this.bgColor = parseColorName(getParameter("BGCOLOR"), Color.black);
Enumeration localEnumeration = parseAndLoadImages(getParameter("IMAGES"));
Font localFont = new Font(str1, j, i);
FontMetrics localFontMetrics = getToolkit().getFontMetrics(localFont);
this.image = createImage(localFontMetrics.stringWidth(str2) + this.imgsWidth + size().width, size().height);
this.scrolled = (-size().width);
parseAndDrawText(this.image.getGraphics(), str2, localFontMetrics, localFont, localEnumeration);
}
private void parseAndDrawText(Graphics paramGraphics, String paramString, FontMetrics paramFontMetrics, Font paramFont, Enumeration paramEnumeration)
{
paramGraphics.setFont(paramFont);
paramGraphics.setColor(this.bgColor);
paramGraphics.fillRect(0, 0, this.image.getWidth(this), this.image.getHeight(this));
paramGraphics.setColor(Color.white);
StringBuffer localStringBuffer = new StringBuffer();
int i = 0; int j = 0;
for (int k = 0; k < paramString.length(); k++)
{
char c = paramString.charAt(k);
if ((c == '#') && (j == 0))
{
if (i != 0)
{
paramGraphics.setColor(parseColorName(localStringBuffer.toString(), Color.white));
localStringBuffer.setLength(0);
i = 0;
}
else
{
i = 1;
}
}
else if ((c == '$') && (i == 0) && (j == 0))
{
try
{
Image localImage = (Image)paramEnumeration.nextElement();
paramGraphics.drawImage(localImage, this.scrollLength, 0, this);
this.scrollLength += localImage.getWidth(this);
}
catch (Exception localException)
{
}
}
else if ((c == '/') && (j == 0))
{
j = 1;
}
else if (i != 0)
{
localStringBuffer.append(c);
}
else
{
if (j == 1) j = 0;
paramGraphics.drawString(String.valueOf(c), this.scrollLength, paramFontMetrics.getAscent());
this.scrollLength += paramFontMetrics.charWidth(c);
}
}
}
private Color parseColorName(String paramString, Color paramColor)
{
if ("red".equals(paramString)) return Color.red;
if ("green".equals(paramString)) return Color.green;
if ("blue".equals(paramString)) return Color.blue;
if ("yellow".equals(paramString)) return Color.yellow;
if ("orange".equals(paramString)) return Color.orange;
if ("white".equals(paramString)) return Color.white;
if ("lightGray".equals(paramString)) return Color.lightGray;
if ("gray".equals(paramString)) return Color.gray;
if ("darkGray".equals(paramString)) return Color.darkGray;
if ("black".equals(paramString)) return Color.black;
if ("cyan".equals(paramString)) return Color.cyan;
if ("magenta".equals(paramString)) return Color.magenta;
if ("pink".equals(paramString)) return Color.pink;
return paramColor;
}
private Enumeration parseAndLoadImages(String paramString)
{
if (paramString == null) return null;
int i = 0;
Vector localVector = new Vector();
StringTokenizer localStringTokenizer = new StringTokenizer(paramString);
MediaTracker localMediaTracker = new MediaTracker(this);
while (localStringTokenizer.hasMoreTokens())
{
try
{
Image localImage = getImage(new URL(getDocumentBase(), localStringTokenizer.nextToken()));
localVector.addElement(localImage);
localMediaTracker.addImage(localImage, i);
localMediaTracker.waitForID(i++);
this.imgsWidth += localImage.getWidth(this);
}
catch (Exception localException)
{
}
}
return localVector.elements();
}
public void start()
{
this.thread = new Thread(this);
this.thread.start();
}
public void stop()
{
this.thread = null;
this.scrolled = (-size().width);
}
public void run()
{
while (Thread.currentThread() == this.thread)
{
long l = System.currentTimeMillis();
if (++this.scrolled > this.scrollLength) this.scrolled = (-size().width);
repaint();
try
{
Thread.sleep(Math.max(this.speed - (System.currentTimeMillis() - l), 0L));
}
catch (InterruptedException localInterruptedException)
{
}
}
}
public boolean mouseEnter(Event paramEvent, int paramInt1, int paramInt2)
{
if (this.url != null) getAppletContext().showStatus("Link: " + this.url.toString());
return true;
}
public boolean mouseExit(Event paramEvent, int paramInt1, int paramInt2)
{
if (this.url != null) getAppletContext().showStatus("");
return true;
}
public boolean mouseUp(Event paramEvent, int paramInt1, int paramInt2)
{
if (this.url != null) getAppletContext().showDocument(this.url, this.target);
return true;
}
public void update(Graphics paramGraphics)
{
paramGraphics.setColor(this.bgColor);
if (this.scrolled < 0)
{
paramGraphics.setColor(this.bgColor);
paramGraphics.fillRect(0, 0, -this.scrolled, size().height);
}
paramGraphics.drawImage(this.image, -this.scrolled, 0, this);
}
public void paint(Graphics paramGraphics)
{
update(paramGraphics);
}
public String getAppletInfo()
{
return "ProScroll version 2.3 by Slava Pestov";
}
}
a java .class file is a compiled file that you cannot read with notepad.
if you want the source code you should try to ask it to the author of the article or you could decompile it.