Adding sound to game. Help needed - java

So I have this code, and I would like to know how could I join it with the rest of my game, 'cause the only way it plays sound now is by selecting this class as a launcher. Also, could I get some info, what exactly is changed and why. I feel like I should get a better understanding of this code, since I just found the code, and pasted it :D
Code:
package main;
import main.Handler;
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.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioPlayer implements LineListener {
boolean playCompleted;
void play(String audioFilePath) {
File audioFile = new File(audioFilePath);
try {
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.addLineListener(this);
audioClip.open(audioStream);
audioClip.start();
while (!playCompleted) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
audioClip.close();
} catch (UnsupportedAudioFileException ex) {
System.out.println("The specified audio file is not supported.");
ex.printStackTrace();
} catch (LineUnavailableException ex) {
System.out.println("Audio line for playing back is unavailable.");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("Error playing the audio file.");
ex.printStackTrace();
}
}
public void update(LineEvent event) {
LineEvent.Type type = event.getType();
if (type == LineEvent.Type.START) {
System.out.println("Playback started.");
} else if (type == LineEvent.Type.STOP) {
playCompleted = true;
System.out.println("Playback completed.");
}
}
public static void main(String[] args) {
String audioFilePath = "res/music/dark_theme.wav";
AudioPlayer player = new AudioPlayer();
player.play(audioFilePath);
}
}'

This class is a fairly normal class to use: Construct an instance, call some methods, and it does what it is expected to do. When you are using it as a launcher, all you're doing is calling the main method, which serves as an example of how to use this class:
public static void main(String[] args) {
String audioFilePath = "res/music/dark_theme.wav";
AudioPlayer player = new AudioPlayer();
player.play(audioFilePath);
}
Just construct an instance, and call play() on it with the name of the audio file intended.
However, be warned that this class isn't really a good example of how to go about doing this, for a few reasons:
It blocks while playing, meaning that you can't start playing sound and go about doing something different at the same time.
It can't play a sound more than once without incurring issues.
So, let's modify this class to not have these issues. This class will let you load a clip into memory, and start it asynchronously (meaning that you start it and then your program keeps running). The start() method starts it to play once, and the loop() method loops it forever. stop() is self-explanatory, and cleanup() should be called to release resources once you no longer need this audio clip. (Of course, if you intend to start playing the clip again soon, you should not cleanup() at that point).
import main.Handler;
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.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioPlayer{
Clip audioClip;
boolean playCompleted;
String path;
public AudioPlayer(String path){
this.path = path;
File audioFile = new File(path);
try {
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
} catch (UnsupportedAudioFileException ex) {
System.out.println("The specified audio file is not supported.");
ex.printStackTrace();
} catch (LineUnavailableException ex) {
System.out.println("Audio line for playing back is unavailable.");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("Error playing the audio file.");
ex.printStackTrace();
}
}
void play() {
audioClip.start();
}
void loop(){
audioClip.loop(Clip.LOOP_CONTINUOUSLY);
}
void stop(){
audioClip.stop();
}
void cleanup(){
audioClip.close();
}
public static void main(String[] args) throws InterruptedException {
String audioFilePath = "res/music/dark_theme.wav";
AudioPlayer player = new AudioPlayer(audioFilePath);
player.play();
// give the sound time to play
while(true){
Thread.sleep(1000);
}
}
}

Related

Getting java.io.IOException:mark/reset not supported after uploading a file to play, pause, resume, loop audio

This is the code I have as of now:
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.util.Scanner;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.sound.sampled.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class changeyouvoice extends Frame implements WindowListener, ActionListener {
JButton upload;
JFileChooser jfc;
int i;
Long currentFrame;
Clip clip;
String status;
public static void main(String[] args) {
// 2nd step
changeyouvoice myWindow = new changeyouvoice();
myWindow.setSize(350, 100);
myWindow.setVisible(true);
}
public changeyouvoice() {
jfc = new JFileChooser();
setLayout(new FlowLayout());
addWindowListener(this);
upload = new JButton("Upload");
add(upload);
upload.addActionListener(this);
// create AudioInputStream object
}
public void actionPerformed(ActionEvent e) {
jfc.setDialogTitle("Select the video of your voice");
jfc.setAcceptAllFileFilterUsed(false);// you are not searching for anything.
// figure out why
FileNameExtensionFilter filter = new FileNameExtensionFilter("Select Audio", "m4a", "mp3", "flac", "wav", "wma",
"aac");
jfc.setFileFilter(filter);
int returnValue = jfc.showOpenDialog(this);
// create AudioInputStream object
if (returnValue == JFileChooser.APPROVE_OPTION) {
try {
if (e.getSource() == upload) {
int x = jfc.showOpenDialog(this);
if (x == JFileChooser.APPROVE_OPTION) {
File fileToBeSent = jfc.getSelectedFile();
File initialFile = new File(fileToBeSent.getAbsolutePath());
try {
// InputStream targetStream;
InputStream targetStream = new FileInputStream(initialFile);
AudioInputStream myvoice = AudioSystem.getAudioInputStream(targetStream); // figure
// out
// how
// its
// created. read the file
// and get audio stream
// create AudioInputStream object
// create clip reference
clip = AudioSystem.getClip();
try {
clip.start();
clip.open(myvoice);
clip.loop(Clip.LOOP_CONTINUOUSLY);
status = "play";
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("1. pause");
System.out.println("2. resume");
System.out.println("3. restart");
System.out.println("4. stop");
System.out.println("5. Jump to specific time");
int c = sc.nextInt();
switch (c) {
case 1:
pause();
break;
case 2:
resumeAudio();
break;
case 3:
restart();
break;
case 4:
stop();
break;
case 5:
System.out.println("Enter time (" + 0 +
", " + clip.getMicrosecondLength() + ")");
long c1 = sc.nextLong();
jump(c1);
break;
}
if (c == 4)
break;
}
sc.close();
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
// create clip reference
// open audioInputStream to the clip
} catch (Exception j) {
// Handle the error...
System.out.println(j.toString());
}
}
}
} catch (Exception png) {
// Handle the error...
System.out.println(png.toString());
} finally {
// ... cleanup that will execute whether or not an error occurred ...
}
}
}
// Method to pause the audio
public void pause() {
if (status.equals("paused")) {
System.out.println("audio is already paused");
return;
}
this.currentFrame = this.clip.getMicrosecondPosition();
clip.stop();
status = "paused";
}
// Method to resume the audio
public void resumeAudio() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
if (status.equals("play")) {
System.out.println("Audio is already " + "being played");
return;
}
clip.close();
resetAudioStream();
clip.setMicrosecondPosition(currentFrame);
clip.start();
status = "play";
}
// Method to restart the audio
public void restart() throws IOException, LineUnavailableException, UnsupportedAudioFileException {
clip.stop();
clip.close();
resetAudioStream();
currentFrame = 0L;
clip.setMicrosecondPosition(0);
clip.start();
status = "play";
}
// Method to stop the audio
public void stop() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
currentFrame = 0L;
clip.stop();
clip.close();
}
// Method to jump over a specific part
public void jump(long c) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
if (c > 0 && c < clip.getMicrosecondLength()) {
clip.stop();
clip.close();
resetAudioStream();
currentFrame = c;
clip.setMicrosecondPosition(c);
clip.start();
status = "play";
}
}
// Method to reset audio stream
public void resetAudioStream() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
AudioInputStream audioInputStream = AudioSystem
.getAudioInputStream(this.getClass().getResource(jfc.getSelectedFile().getAbsolutePath()));
clip.open(audioInputStream);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
public void windowOpened(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
}
The code works fine when uploading a file, but for some reason I am not able to play, pause, or resume the audio. I used several tutorials to get the functions to help play the audio, but when I uploaded the file I had to upload it twice and an exception was displayed which was
/Users/thevladimirgeorge/Downloads/Vlad's story.mp3
java.io.IOException: mark/reset not supported
I wonder what was the issue going on with the code. The app I used to code is Visual Studio Code.
If you provide a URL instead of an InputStream as an argument to AudioSystem.getAudioStream, the requirement that the media resource supports marking and resetting is circumvented. This can be observed by comparing the APIs for the two methods.
AudioSystem.getAudioInputStream(InputStream)
AudioSystem.getAudioInputStream(URL)
Only the method that takes InputStream includes these checks:
The implementation of this method may require multiple parsers to
examine the stream to determine whether they support it. These parsers
must be able to mark the stream, read enough data to determine whether
they support the stream, and reset the stream's read pointer to its
original position. If the input stream does not support these
operations, this method may fail with an IOException.
So, rewriting the code to obtain a URL for your resource instead of an InputStream should solve your problem, unless you explicitly need to have the AudioInputStream support marking and resetting. I've not come across such a scenario myself. Would be interesting in learning about situations where this capability is used.
EDIT: I overlooked that you are trying to load an mp3. Java doesn't directly support this or many of the other files on your list of audio. You will need to include additional libraries and code to handle these. The following (executed in jshell) can show what formats are supported:
jshell> import javax.sound.sampled.*;
jshell> AudioFileFormat.Type[] types = AudioSystem.getAudioFileTypes();
types ==> AudioFileFormat$Type[3] { WAVE, AU, AIFF }
More documentation can be found in the JavaSound section of the TroubleShooting Guide.

How to halt a clip/object in a certain time?

Hi Stackoverflow!
So basically, I have two audio clips going on in my Java program and I want one of them to stop at a certain time and the other to start at a certain time.
I'll try to explain the code the best I can.
http://pastebin.com/1zGdb30x Music.java
package testingground;
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Music {
public void musictwo() {
URL url;
try {
url = new URL("file:///D:/Yes/GUI/song.wav");
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.
getAudioInputStream( url );
clip.open(ais);
clip.loop(100);
} catch (UnsupportedAudioFileException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void musicone() {
URL url;
try {
url = new URL("file:///D:/Yes/GUI/rival.wav");
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.
getAudioInputStream( url );
clip.open(ais);
clip.loop(100);
} catch (UnsupportedAudioFileException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
http://pastebin.com/nGm4DZfr Program.java
package testingground;
import javax.swing.JOptionPane;
public class Program {
public static void main(String[] args) {
System.out.println("The first song should play now!");
Music a = new Music();
a.musicone();
System.out.println("The second song should play now!");
a.musictwo();
JOptionPane.showMessageDialog(null,"Press 'ok' to end the application.");
}
}
In Music.java, I have the audio files working and they are only local .wav files that are only available on my computer. In program.java, the output is musicone and musictwo both play at the same time. Is there a way so that muscone plays, stops, then musictwo plays?
Things I have tried-
- Have an if and else statement in program.java to execute clip.stop(). No errors, it just didn't work.
- Have an if and else boolean from program.java to execute clip.stop() in Music.java. No syntax errors, it just didn't work.
The way I understand your question, you can use a LineListener.
Just, for example, here is a class that goes through a List, playing the next stream each time the current one completes:
class Playlist implements LineListener {
private final List<AudioInputStream> list = new ArrayList<>();
private Clip clip;
private int next;
#Override
public void update(LineEvent evt) {
if(evt.getType() == LineEvent.STOP) {
try {
playNext();
} catch(LineUnavailableException | IOException e) {
e.printStackTrace();
}
}
}
void enqueue(AudioInputStream ais) {
synchronized(this) {
list.add(ais);
}
}
void playNext() throws LineUnavailableException, IOException {
synchronized(this) {
if(list.isEmpty()) {
throw new IllegalStateException();
}
if(clip != null) {
if(clip.isRunning()) clip.stop();
if(clip.isOpen()) clip.close();
}
clip = AudioSystem.getClip();
clip.addLineListener(listener);
try {
clip.open(list.get(next));
} finally {
next = (next + 1) % list.size();
}
clip.start();
}
}
}

Clear data from Clip/AudioStream to free up memory

I have some code that serves as a super basic music player:
import java.io.File;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class MusicPlayer{
private Clip c;
private boolean playing;
public MusicPlayer(){
playing = false;
}
public void play(String fileName) {
if(playing == false){
try {
c.drain();
c.flush();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(fileName));
c = AudioSystem.getClip();
c.open(audioInputStream);
c.start();
playing = true;
} catch(Exception ex) {
System.out.println("Error with playing sound:" + ex);
ex.printStackTrace();
}
}
}
public void stop(){
if(playing == true){
c.stop();
playing = false;
}
}
}
The problem is that if I try to open too many wav files, the program crashes with an OutOfMemoryError. Giving the program more memory to work with (less than ideal to begin with) still means that the program runs slower each time a new file is opened. You can see I tried to solve this with:
c.drain();
c.flush();
but plainly this is not enough. Any help is appreciated!

How to make sound loop using this method?

I did sound in a REALLY wierd way, do you think that there may be a way to loop it? cuz it only plays once then stops. Here is code for sound:
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.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class Sound {
private final static int BUFFER_SIZE = 12800000;
private static File soundFile;
private static AudioInputStream audioStream;
private static AudioFormat audioFormat;
private static SourceDataLine sourceLine;
/**
*
* #param filename the name of the file that is going to be played
*
*/
public static void playSound(String filename){
String strFilename = filename;
try {
soundFile = new File(strFilename);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
try {
audioStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e){
e.printStackTrace();
System.exit(1);
}
audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
try {
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
} catch (LineUnavailableException e) {
e.printStackTrace();
System.exit(1);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
sourceLine.start();
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
try {
nBytesRead = audioStream.read(abData, 0, abData.length);
} catch (IOException e) {
e.printStackTrace();
}
if (nBytesRead >= 0) {
#SuppressWarnings("unused")
int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
}
}
sourceLine.drain();
sourceLine.close();
}
}
To activate it i do:
new Thread(new Runnable() {
public void run() {
Sound.playSound("hurt.au");
}
}).start();
(if i do just Sound.playSound("hurt.au"); the game freezes because the sound plays on the games main thread so i put the sound in it's own thread to save the game from freezing)
So the question is, how do i loop it?
You will need some sort of test to see whether the sound currently playing is finished or not. If you are making a game, I might suggest using some libraries to make it easier. Such as slick2d. This has inbuilt functions to loop a sound instead of just playing it once. If you choose not to, you will have to keep track of the thread and on every update of your game state look at the sound object and ask the sourceline if it has finished playing or not. If it has then sourceline.start() else no-op. You could also put the thread inside the sound.playsound method itself, thereby making your code a little bit less coupled.
http://www.slick2d.org/
I really recommend using a 3rd party library to make it easier on yourself though.

Trying to play music in Java: java.lang.IllegalArgumentException: Invalid format

this is the first time for me that I try to use a song within my code.
I have been following a webpage which explains how to play songs (http://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html), but I run into the error ava.lang.IllegalArgumentException: Invalid format.
I don't understand why this happens and what I could do to play a song.
This is the code that doesn't work:
private void startMusic() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
// from a wave File
File soundFile = new File("/home/simone/OhHa/Pakman02/src/main/java/Pakman/ArsenioLupin.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
// For small-size file only. Do not use this to open a large file over slow network, as it blocks.
// start()
clip.start(); // play once
// Loop()
// clip.loop(0); // repeat none (play once), can be used in place of start().
// clip.loop(5); // repeat 5 times (play 6 times)
clip.loop(Clip.LOOP_CONTINUOUSLY); // repeat forever
}
Any suggestions?
try this. note the import of the javax.sound.sampled.*
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;
public class SoundClipTest extends JFrame {
// Constructor
public SoundClipTest() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test Sound Clip");
this.setSize(300, 200);
this.setVisible(true);
try {
// Open an audio input stream.
URL url = this.getClass().getClassLoader().getResource("/home/simone/OhHa/Pakman02/src/main/java/Pakman/ArsenioLupin.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);
// Get a sound clip resource.
Clip clip = AudioSystem.getClip();
// Open audio clip and load samples from the audio input stream.
clip.open(audioIn);
clip.start();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new SoundClipTest();
}
}
an alternative is
import javax.swing.*;
import sun.audio.*;
import java.awt.event.*;
import java.io.*;
public class Sound {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(200,200);
JButton button = new JButton("Click me");
frame.add(button);
button.addActionListener(new AL());
frame.show(true);
}
public static class AL implements ActionListener{
public final void actionPerformed(ActionEvent e){
music();
}
}
public static void music(){
AudioPlayer MGP = AudioPlayer.player;
AudioStream BGM;
AudioData MD;
ContinuousAudioDataStream loop = null;
try{
BGM = new AudioStream(new FileInputStream("C:\home\simone\OhHa\Pakman02\src\main\java\Pakman\ArsenioLupin.wav"));
MD = BGM.getData();
loop = new ContinuousAudioDataStream(MD);
}catch(IOException error){
System.out.print("file not found");
}
MGP.start(loop);
}
}

Categories