Better way of resetting java AudioStream - java

As of now, i am using AudioPlayer to create sound effects for my game, and I am struggling to find an easy way to reset the audio before I begin playing it again. As of now I am just reloading the AudioStream entirely, heres my code, any suggestions are welcome.
package resources;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import javax.sound.sampled.Clip;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
public class Audio {
private static HashMap<String, AudioStream> sounds = new HashMap<String, AudioStream>();
private static HashMap<String, Long> times = new HashMap<String, Long>();
Clip c;
public static AudioStream getAudio(String s){
if(sounds.containsKey(s))
return sounds.get(s);
return null;
}
public static void loadAllAudio(){
File f = new File("res/sounds");
String[] files = f.list();
for(String s:files){
if(s.endsWith(".wav")){
loadAudio(s);
System.out.println("Loaded Audio: "+s);
}
}
}
public static double getSoundLength(String sound){
return getAudio(sound).getLength()/192000.0;
}
public static void playSound(String name){
resetSound(name);
times.put(name, System.nanoTime());
AudioPlayer.player.start(sounds.get(name));
}
public static void resetSound(String name){
loadAudio(name);
}
public static void stopSound(String sound){
AudioPlayer.player.stop(sounds.get(sound));
times.put(sound, System.nanoTime());
}
private static void loadAudio(String name){
try {
File f = new File("res/sounds/"+name);
sounds.put(name, new AudioStream(new FileInputStream(f)));
times.put(name, 0L);
} catch (Exception e) {}
}
public static double getTime(String sound) {
long time = times.get(sound);
if(time==0)
return 0;
return (System.nanoTime()-time)/1E9;
}
}
The line I would like to replace is:
public static void playSound(String name){
---------resetSound(name);--------- THIS LINE
times.put(name, System.nanoTime());
AudioPlayer.player.start(sounds.get(name));
}

You can use JLayer which supports .mp3
An example how to play sound with JLayer:
new Thread(()->{
try {
FileInputStream file = new FileInputStream("path ..../audio.mp3"); //initialize the FileInputStream
Player player= new Player(file); //initialize the player
player.play(); //start the player
} catch (Exception e) {
e.printStackTrace();
}
}).start();
Note:
Note that i am using a separate Thread cause if not the App will stack.

Related

I'm trying to read a text file and store it in an arraylist of objects

I'm trying to read a text file and store it in an arraylist of objects, but I keep getting an error saying I cannot convert a String to an Item, which is type of arraylist I am using. I have tried various solutions, but am not quite sure how its is suppossed to be done. I am new to coding and have this assignment due soon. Anything helps!
private void loadFile(String FileName)
{
Scanner in;
Item line;
try
{
in = new Scanner(new File(FileName));
while (in.hasNext())
{
line = in.nextLine();
MyStore.add(line);
}
in.close();
}
catch (IOException e)
{
System.out.println("FILE NOT FOUND.");
}
}
my apologies for not adding the Item class
public class Item
{
private int myId;
private int myInv;
//default constructor
public Item()
{
myId = 0;
myInv = 0;
}
//"normal" constructor
public Item(int id, int inv)
{
myId = id;
myInv = inv;
}
//copy constructor
public Item(Item OtherItem)
{
myId = OtherItem.getId();
myInv = OtherItem.getInv();
}
public int getId()
{
return myId;
}
public int getInv()
{
return myInv;
}
public int compareTo(Item Other)
{
int compare = 0;
if (myId > Other.getId())
{
compare = 1;
}
else if (myId < Other.getId())
{
compare = -1;
}
return compare;
}
public boolean equals(Item Other)
{
boolean equal = false;
if (myId == Other.getId())
{
equal = true;;
}
return equal;
}
public String toString()
{
String Result;
Result = String.format("%8d%8d", myId, myInv);
return Result;
}
}
This is the creation of my arraylist.
private ArrayList MyStore = new ArrayList ();
Here is a sample of my text file.
3679 87
196 60
12490 12
18618 14
2370 65
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.mycompany.rosmery;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* #author Sem-6-INGENIERIAINDU
*/
public class aaa {
public static void main(String arg[]) throws FileNotFoundException, IOException{
BufferedReader files=new BufferedReader(new FileReader(new File("")));
List<String> dto=new ArrayList<>();
String line;
while((line= files.readLine())!= null){
line= files.readLine();
dto.add(line);
//Hacer la logica para esos datos
}
}
}
in.nextLine() returns a String.
So, you cannot assign in.nextLine() to an instance of Item.
Your code may need to correct it as:
List<String> myStore = new ArrayList<String>();
private void loadFile(String FileName)
{
Scanner in;
try
{
in = new Scanner(new File(FileName));
while (in.hasNext())
{
myStore.add(in.nextLine());
}
in.close();
}
catch (IOException e)
{
System.out.println("FILE NOT FOUND.");
}
}
If you want to have a list of Item after reading a file, then you need provide the logic that convert given line of information into an instance of Item.
let's say your file content is in the following format.
id1,inv1
id2,inv2
.
.
Then, you can use the type Item as the following.
List<Item> myStore = new ArrayList<Item>();
private void loadFile(String FileName)
{
Scanner in;
String[] line;
try
{
in = new Scanner(new File(FileName));
while (in.hasNext())
{
line = in.nextLine().split(",");
myStore.add(new Item(line[0], line[1]));
}
in.close();
}
catch (IOException e)
{
System.out.println("FILE NOT FOUND.");
}
}
One of the possible solutions (assuming that the data in file lines is separated by a comma), with using streams:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws IOException {
List<Item> items = loadFile("myfile.txt");
System.out.println(items);
}
private static List<Item> loadFile(String fileName) throws IOException {
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
return stream
.map(s -> Stream.of(s.split(",")).mapToInt(Integer::parseInt).toArray())
.map(i -> new Item(i[0], i[1]))
.collect(Collectors.toList());
}
}
}
or with foreach:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws IOException {
List<Item> items = new ArrayList<>();
for (String line : loadFile("myfile.txt")) {
String[] data = line.split(",");
int id = Integer.parseInt(data[0]);
int inv = Integer.parseInt(data[1]);
items.add(new Item(id, inv));
}
System.out.println(items);
}
private static List<String> loadFile(String fileName) throws IOException {
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
return stream.collect(Collectors.toList());
}
}
}

How to deserialize objects after closing an opening program in Java 11

I have a program in which I am trying to implement saving and loading of obejcts, however I couldn't get the loading to work after the program closes, so effectively only saving and loading works while the program is open, but no data is ever loaded once the program starts. I assume this is something to do with overwiting. I created a test program to see if I could get it to work just using a simple Person class. I store my Peson objects inside an ArrayList and serialize it, then deserialize it. Currently I am storing all loaded Person objects in a JComboBox. I have looked online and could not find anything that will help. Also note I am aware that using serialization is not the best method of saving objects, but it's something suitable to use for my program.
My App Class:
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;
public class App extends JFrame {
public static JComboBox<Person> peopleBox;
public App(){
try {
Person.peopleList = loadList();
}
catch(IOException | ClassNotFoundException e){
System.out.println(e.getMessage());
}
try {
saveList(Person.peopleList);
}catch (IOException e){
System.out.println(e.getMessage());
}
peopleBox = new JComboBox<>();
peopleBox.setModel(getComboBoxModel(Person.peopleList));
add(peopleBox);
pack();
setSize(600, 400);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public DefaultComboBoxModel<Person> getComboBoxModel(ArrayList<Person> peopleList){
Person[] comboBoxModel = peopleList.toArray(new Person[0]);
return new DefaultComboBoxModel<>(comboBoxModel);
}
public static void saveList(ArrayList<Person> peopleList) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.bin"));
objectOutputStream.writeObject(peopleList);
}
public static ArrayList<Person> loadList() throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.bin"));
Person.peopleList = (ArrayList<Person>) objectInputStream.readObject();
return Person.peopleList;
}
public static void main(String[] args){
// Person p = new Person("Sean", 22);
try {
saveList(Person.peopleList);
}catch (IOException e){
System.out.println(e.getMessage());
}
App app = new App();
app.pack();
app.setVisible(true);
}
}
Person Class
import java.io.Serializable;
import java.util.ArrayList;
public class Person implements Serializable {
public int age;
public String name;
public static ArrayList<Person> peopleList = new ArrayList<>();
public Person(String name, int age){
this.age = age;
this.name = name;
peopleList.add(this);
for(Person p : peopleList){
System.out.println(p.toString());
}
}
public Person(){
}
public String toString(){
return "Name : " + name + " Age: " + age;
}
}
I expect when I save the list to the "test.bin" file, close the program, then open it again that it will load the list and display the Objects I created before I closed the program. I appreciate any help, thanks.
You are saving an empty list before you load Person from the file.
I suggest this approach:
import javax.swing.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class App extends JFrame {
public static JComboBox<Person> peopleBox;
public App() {
try {
loadList();
} catch (IOException | ClassNotFoundException e) {
System.out.println(e.getMessage());
}
try {
saveList(Person.peopleList);
} catch (IOException e) {
System.out.println(e.getMessage());
}
setSize(600, 400);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public void updateData(){
peopleBox = new JComboBox<>();
peopleBox.setModel(getComboBoxModel(Person.peopleList));
add(peopleBox);
pack();
}
public DefaultComboBoxModel<Person> getComboBoxModel(ArrayList<Person> peopleList) {
Person[] comboBoxModel = peopleList.toArray(new Person[0]);
return new DefaultComboBoxModel<>(comboBoxModel);
}
public static void saveList(ArrayList<Person> peopleList) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.bin"));
objectOutputStream.writeObject(peopleList);
}
public static void loadList() throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.bin"));
Person.peopleList.addAll((List<Person>) objectInputStream.readObject());
}
public static void main(String[] args) {
App app = new App();
Person p = new Person("Sean2", 24);
try {
saveList(Person.peopleList);
} catch (IOException e) {
System.out.println(e.getMessage());
}
app.updateData();
app.setVisible(true);
}
}

How to play a wav file using Java?

I would like to play a wav file and after I googled it I found this script but it doesn't work.
(It didn't throw any exceptions nor have compiling problems)
import java.io.File;
import films.Film;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class MusicStorage {
/**
* Opens a wav file and plays it
* #param args
*/
public void play(Film song) {
try {
Clip sound = AudioSystem.getClip();
sound.open(AudioSystem.getAudioInputStream(new File(song.getClip())));
sound.start();
while (sound.isRunning())
Thread.sleep(1000);
sound.close();
} catch (Exception e) {
System.out.println("Whatever" + e);
}
}
}
import audio.MusicStorage;
import films.Film;
public class Aplication {
private static Film gladiator = new Film("Gladiator", "gladiator.wav");
private static MusicStorage storage = new MusicStorage();
public static void main(String[] args) {
storage.play(gladiator);
}
}
public class Film {
private String name;
private String clip;
public Film(String name, String clip) {
this.name = name;
this.clip = clip;
}
public String getClip() {
return clip;
}
public String getName() {
return name;
}
}
I have added all the code that I have so I hope it would be clear to solve my problem
Just remove the while loop from your code and it should be fixed. The while loop is making the thread sleep so it can't play the audio file.
public void play(Film song) {
try {
Clip sound = AudioSystem.getClip();
sound.open(AudioSystem.getAudioInputStream(new File(song.getClip())));
sound.start();
} catch (Exception e) {
System.out.println("Whatever" + e);
}
}
}

Sounds won't play in java.. JFrame and Canvas not Applet

I'm currently working on my first game in java and i'm trying to implement sounds when the spaceship is getting hit.. this is my code . I get a null pointer exception but my sound is in the right place "workspace/project/src/sounds/"
public class GameSounds
{
public static synchronized void hit()
{
try
{
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(GameSounds.class.getResourceAsStream("sounds/8bit_bomb_explosion.wav"));
clip.open(inputStream);
clip.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
here is the stacktrace
java.lang.NullPointerException
at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(Unknown Source)
at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
at sound.GameSounds.hit(GameSounds.java:16)
at main.Main.doLogic(Main.java:135)
at main.Main.run(Main.java:101)
at java.lang.Thread.run(Unknown Source)
package sound;
import java.io.InputStream;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class GameSounds
{
public static synchronized void hit()
{
try
{
String resPath = "/sounds/8bit_bomb_explosion.wav"; // *** this is the key ***
InputStream audioInStream = GameSounds.class.getResourceAsStream(resPath);
System.out.println("is audioInStream null?: " + (audioInStream == null)); // test it!
AudioInputStream inputStream = AudioSystem.getAudioInputStream(audioInStream); Clip clip = AudioSystem.getClip();
clip.open(inputStream);
clip.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
thanks for advices now it works
In all likelihood, you are not getting the resource with the correct path. Understand that resource paths are based on where the class loader looks to load class files and not on where the src or "user.dir" directory is.
Perhaps you want to do:
// almost always better to break up a long code line into smaller lines.
String resPath = "/sounds/8bit_bomb_explosion.wav"; // *** this is the key ***
InputStream audioInStream = GameSounds.class.getResourceAsStream(resPath);
System.out.println("is audioInStream null?: " + (audioInStream == null)); // test it!
AudioInputStream inputStream = AudioSystem.getAudioInputStream(audioInStream);
Again the path String will depend on where your class files are located in relation to your src directory.
I have had the same problems. But after searching for hours I found Javazoom which is a external libery you can import into your project and makes it much more easy to play sounds:
http://www.javazoom.net/index.shtml
You can use it like this:
import javazoom.jl.player.advanced.*;
class SoundJLayer extends PlaybackListener implements Runnable
{
private String filePath;
private AdvancedPlayer player;
private Thread playerThread;
public SoundJLayer(String filePath)
{
this.filePath = filePath;
}
public void play()
{
try
{
String urlAsString =
"file:///"
+ new java.io.File(".").getCanonicalPath()
+ "/"
+ this.filePath;
this.player = new AdvancedPlayer
(
new java.net.URL(urlAsString).openStream(),
javazoom.jl.player.FactoryRegistry.systemRegistry().createAudioDevice()
);
this.player.setPlayBackListener(this);
this.playerThread = new Thread(this, "AudioPlayerThread");
this.playerThread.start();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public void stop() {
player.stop();
}
// PlaybackListener members
public void playbackStarted(PlaybackEvent playbackEvent)
{
}
public void playbackFinished(PlaybackEvent playbackEvent)
{
}
// Runnable members
public void run()
{
try
{
this.player.play();
}
catch (javazoom.jl.decoder.JavaLayerException ex)
{
ex.printStackTrace();
}
}
}
After that you just have to create a new SoundJLayer-Object and start ir with play()
Hope this is helpful,
Jan

How to load media resources from the classpath in JMF

I have a Java application that I want to turn into an executable jar. I am using JMF in this application, and I can't seem to get the sound files working right...
I create the jar using
jar cvfm jarname.jar manifest.txt *.class *.gif *.wav
So, all the sound files get put inside the jar, and in the code, I am creating the Players using
Player player = Manager.createPlayer(ClassName.class.getResource("song1.wav"));
The jar is on my desktop, and when I attempt to run it, this exception occurs:
javax.media.NoPlayerException: Cannot find a Player for :jar:file:/C:/Users/Pojo/
Desktop/jarname.jar!/song1.wav
...It's not getting IOExceptions, so it seems to at least be finding the file itself all right.
Also, before I used the getResource, I used to have it like this:
Player player = Manager.createPlayer(new File("song1.wav").toURL());
and it was playing fine, so I know nothing is wrong with the sound file itself.
The reason I am trying to switch to this method instead of the File method is so that the sound files can be packaged inside the jar itself and not have to be its siblings in a directory.
This is a far cry from production code, but this seems resolved any runtime exceptions (though it's not actually wired up to play anything yet):
import javax.media.Manager;
import javax.media.Player;
import javax.media.protocol.URLDataSource;
// ...
URL url = JmfTest.class.getResource("song1.wav");
System.out.println("url: " + url);
URLDataSource uds = new URLDataSource(url);
uds.connect();
Player player = Manager.createPlayer(uds);
New solution:
First, a custom DataSource class that returns a SourceStream that implements Seekable is needed:
package com.ziesemer.test;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.media.Duration;
import javax.media.MediaLocator;
import javax.media.Time;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.PullDataSource;
import javax.media.protocol.PullSourceStream;
import javax.media.protocol.Seekable;
/**
* #author Mark A. Ziesemer
* <www.ziesemer.com>
*/
public class JarDataSource extends PullDataSource{
protected JarURLConnection conn;
protected ContentDescriptor contentType;
protected JarPullSourceStream[] sources;
protected boolean connected;
public JarDataSource(URL url) throws IOException{
setLocator(new MediaLocator(url));
connected = false;
}
#Override
public PullSourceStream[] getStreams(){
return sources;
}
#Override
public void connect() throws IOException{
conn = (JarURLConnection)getLocator().getURL().openConnection();
conn.connect();
connected = true;
JarFile jf = conn.getJarFile();
JarEntry je = jf.getJarEntry(conn.getEntryName());
String mimeType = conn.getContentType();
if(mimeType == null){
mimeType = ContentDescriptor.CONTENT_UNKNOWN;
}
contentType = new ContentDescriptor(ContentDescriptor.mimeTypeToPackageName(mimeType));
sources = new JarPullSourceStream[1];
sources[0] = new JarPullSourceStream(jf, je, contentType);
}
#Override
public String getContentType(){
return contentType.getContentType();
}
#Override
public void disconnect(){
if(connected){
try{
sources[0].close();
}catch(IOException e){
e.printStackTrace();
}
connected = false;
}
}
#Override
public void start() throws IOException{
// Nothing to do.
}
#Override
public void stop() throws IOException{
// Nothing to do.
}
#Override
public Time getDuration(){
return Duration.DURATION_UNKNOWN;
}
#Override
public Object[] getControls(){
return new Object[0];
}
#Override
public Object getControl(String controlName){
return null;
}
protected class JarPullSourceStream implements PullSourceStream, Seekable, Closeable{
protected final JarFile jarFile;
protected final JarEntry jarEntry;
protected final ContentDescriptor type;
protected InputStream stream;
protected long position;
public JarPullSourceStream(JarFile jarFile, JarEntry jarEntry, ContentDescriptor type) throws IOException{
this.jarFile = jarFile;
this.jarEntry = jarEntry;
this.type = type;
this.stream = jarFile.getInputStream(jarEntry);
}
#Override
public ContentDescriptor getContentDescriptor(){
return type;
}
#Override
public long getContentLength(){
return jarEntry.getSize();
}
#Override
public boolean endOfStream(){
return position < getContentLength();
}
#Override
public Object[] getControls(){
return new Object[0];
}
#Override
public Object getControl(String controlType){
return null;
}
#Override
public boolean willReadBlock(){
if(endOfStream()){
return true;
}
try{
return stream.available() == 0;
}catch(IOException e){
return true;
}
}
#Override
public int read(byte[] buffer, int offset, int length) throws IOException{
int read = stream.read(buffer, offset, length);
position += read;
return read;
}
#Override
public long seek(long where){
try{
if(where < position){
stream.close();
stream = jarFile.getInputStream(jarEntry);
position = 0;
}
long skip = where - position;
while(skip > 0){
long skipped = stream.skip(skip);
skip -= skipped;
position += skipped;
}
}catch(IOException ioe){
// Made a best effort.
ioe.printStackTrace();
}
return position;
}
#Override
public long tell(){
return position;
}
#Override
public boolean isRandomAccess(){
return true;
}
#Override
public void close() throws IOException{
try{
stream.close();
}finally{
jarFile.close();
}
}
}
}
Then, the above custom data source is used to create a player, and a ControllerListener is added to cause the player to loop:
package com.ziesemer.test;
import java.net.URL;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.EndOfMediaEvent;
import javax.media.Manager;
import javax.media.Player;
import javax.media.Time;
/**
* #author Mark A. Ziesemer
* <www.ziesemer.com>
*/
public class JmfTest{
public static void main(String[] args) throws Exception{
URL url = JmfTest.class.getResource("Test.wav");
JarDataSource jds = new JarDataSource(url);
jds.connect();
final Player player = Manager.createPlayer(jds);
player.addControllerListener(new ControllerListener(){
#Override
public void controllerUpdate(ControllerEvent ce){
if(ce instanceof EndOfMediaEvent){
player.setMediaTime(new Time(0));
player.start();
}
}
});
player.start();
}
}
Note that without the custom data source, JMF tries repeatedly to seek back to the beginning - but fails, and eventually gives up. This can be seen from debugging the same ControllerListener, which will receive a several events for each attempt.
Or, using the MediaPlayer approach to loop (that you mentioned on my previous answer):
package com.ziesemer.test;
import java.net.URL;
import javax.media.Manager;
import javax.media.Player;
import javax.media.bean.playerbean.MediaPlayer;
/**
* #author Mark A. Ziesemer
* <www.ziesemer.com>
*/
public class JmfTest{
public static void main(String[] args) throws Exception{
URL url = JmfTest.class.getResource("Test.wav");
JarDataSource jds = new JarDataSource(url);
jds.connect();
final Player player = Manager.createPlayer(jds);
MediaPlayer mp = new MediaPlayer();
mp.setPlayer(player);
mp.setPlaybackLoop(true);
mp.start();
}
}
Again, I would not consider this production-ready code (could use some more Javadocs and logging, etc.), but it is tested and working (Java 1.6), and should meet your needs nicely.
Merry Christmas, and happy holidays!
Manager.createPlayer(this.getClass().getResource("/song1.wav"));
That will work if the song1.wav is in the root of a Jar that is on the run-time class-path of the application.

Categories

Resources