Get audio to play in JAR File - java

I know this question has been asked many times and I've looked at many in hopes to figure out my problems, but it didn't really help much. I was given this class to use to play WAV files on my GUI and it works when retrieving local files. But it doesn't work in a JAR file. I know this is because the music class only works for retrieving local files, so I need help changing the code to retrieve music files from the JAR.
Here's the SoundPlayer class:
package extra;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.sound.sampled.AudioInputStream;
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.UnsupportedAudioFileException;
import org.pscode.xui.sound.bigclip.BigClip;
/**
* A class to play audio clips. Caches previously-played clips,
* allowing fast re-playback of previously played sounds.
*
* #author Anon
* #version 1.51
*/
public class SoundPlayer {
/** A cache of previously-played audio clips. */
private final Map<String, Clip> myClips = new HashMap<String, Clip>();
/**
* Plays the audio file with the given file name.
* This method returns instantly, without waiting for the clip to finish playing.
*
* #param theFilename The name of the file to play.
* #return a Clip object representing the sound played.
* #throws IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip play(final String theFilename) throws IllegalArgumentException {
return loop(theFilename, 1);
}
/**
* Plays the clip with the given file name in a continuous loop.
* The clip keeps looping until it is later stopped by calling the
* stop() method. This function returns instantly
*
* #param theFilename The name of the file to play.
* #return a Clip object representing the sound played.
* #throws IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip loop(final String theFilename) throws IllegalArgumentException {
return loop(theFilename, Clip.LOOP_CONTINUOUSLY);
}
/**
* Plays the clip with the given file name in a loop.
* The clip loops until it has played the specified number of times,
* or until it is later stopped by calling the stop() method.
* This function returns instantly, without waiting for the clip to finish looping.
*
* #param theFilename The name of the file to play.
* #param theNumberOfTimes The number of times to loop the clip.
* #return a Clip object representing the sound played.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip loop(final String theFilename, final int theNumberOfTimes)
throws IllegalArgumentException {
final Clip clip = getClip(theFilename);
if (clip != null) {
clip.loop(theNumberOfTimes);
}
return clip;
}
/**
* Pauses the clip with the given file name.
* If the clip is later played, it will resume from where it was paused.
* Calling this method does not resume a thread that is
* suspended on a playAndWait() or a loopAndWait().
*
* If stop() is called on a paused clip, it will reset to the
* beginning of the clip for the next play.
*
* #param theFilename The name of the file to pause.
* #exception IllegalArgumentException if there is a problem reading from
* or playing the sound file.
*/
public void pause(final String theFilename) throws IllegalArgumentException {
final Clip clip = getClip(theFilename);
if (clip != null) {
final int pos = clip.getFramePosition();
clip.stop();
clip.setFramePosition(pos);
}
}
/**
* Stops the clip with the specified filename
* (and wakes up any threads waiting for it to finish playing).
*
* #param theFilename The name of the file to stop.
* #return a Clip object representing the sound stopped.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip stop(final String theFilename)
throws IllegalArgumentException {
final Clip clip = getClip(theFilename);
stopClip(clip);
return clip;
}
/**
* Stops all currently playing sound clips
* (and wakes up the threads waiting for them to finish playing).
*/
public void stopAll() {
for (final Clip clip : myClips.values()) {
stopClip(clip);
}
}
/**
* Preloads the clip at the given file name.
* This means the clip will be available faster, when requested for playing the first time.
* #param theFilename The name of the file to preload.
* #return a Clip object representing the preloaded sound.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip preLoad(final String theFilename)
throws IllegalArgumentException {
return getClip(theFilename);
}
/**
* Returns a Clip object for a filename, either by creating
* a new one or loading it from the cache.
*
* #param theFilename The name of the file to load.
* #return a Clip object, or null if one is not found.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
private Clip getClip(final String theFilename) throws IllegalArgumentException {
BigClip clip = null;
AudioInputStream ais = null;
if (myClips.containsKey(theFilename)) {
clip = (BigClip) myClips.get(theFilename);
} else {
// read audio file from disk
try {
ais = AudioSystem.getAudioInputStream(new File(theFilename));
clip = new BigClip();
clip.open(ais);
clip.addLineListener(new LineListener() {
/**
* Responds to audio events generated by clips.
*
* #param theEvent The event generated.
*/
public void update(final LineEvent theEvent) {
if (theEvent.getType() == LineEvent.Type.STOP) {
// clip is done playing
stopClip((Clip) theEvent.getSource());
}
}
});
myClips.put(theFilename, clip);
} catch (final UnsupportedAudioFileException uafe) {
throw new IllegalArgumentException
("Not a valid supported audio file: \"" + theFilename + "\"", uafe);
} catch (final LineUnavailableException lue) {
lue.printStackTrace();
throw new IllegalArgumentException
("Line is not available to play sound \"" + theFilename + " \"", lue);
} catch (final IOException ioe) {
throw new IllegalArgumentException
("I/O error while reading file: \"" + theFilename + "\" ", ioe);
}
}
return clip;
}
/**
* Stops the playing of the specified clip.
*
* #param theClip The clip.
*/
private void stopClip(final Clip theClip) {
if (theClip != null) {
synchronized (theClip) {
theClip.stop();
theClip.setFramePosition(0);
theClip.notifyAll(); // awaken threads waiting for this Clip
}
}
}
}
// end of class SoundPlayer
In the getClip() method, I think that's where there needs to be a change since that's where the AudioInputStream is grabbing local files. I'm just not sure how to change it though.

Files in a jar file can't actually be retrieved as a file. Instead, you need to use the Class object (usually the this variable)'s .getResource to retrieve a URL or .getResourceAsStream to retrieve an InputStream for it.
You can then pass either of these into one of AudioSystem.getAudioInputStream's overloads as it has one for InputStreams and one for URLs.

Use ClassLoader.getSystemResource("path/inside/of/jar").
If the goal is to simply play sound:
Try TinySound. I recently used this in a project I'm working on, and it's mindblowingly easy to use. Make sure you use either .wav or .ogg files though, you can use http://media.io/ to convert to both of those.

Related

How can I play audio in java with command line interface?

I have been searching for how to play audio in java ( textpad ). There are plenty of examples but they use a GUI. I am using a command line interface. How do I play audio and use key event e.g spacebar to pause the audio and press spacebar again to replay the audio?
I do not know which examples you have been looking at but I do not think the GUI has anything to do with IF you can play sounds.
The following code is a simple sound class you can use in order to play audio in Java, you can read more about it at this Documentation.
import javax.sound.sampled.*;
import java.io.IOException;
import java.net.URL;
public class Sound {
private URL url;
private Clip clip;
/**
* #param requestedSound The requested type of sound
*/
public Sound(String requestedSound) {
url = this.getClass().getResource(requestedSound);
if (url != null) {
try {
// Open an audio input stream.
// Get a sound clip resource.
// Open audio clip and load samples from the audio input stream.
AudioInputStream audioInput = AudioSystem.getAudioInputStream(url);
clip = AudioSystem.getClip();
clip.open(audioInput);
} catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) {
e.printStackTrace();
}
}
}
/**
* Plays the sound
*/
public void play() {
clip.setFramePosition(0);
clip.start();
}
}
To use it you simply create a sound in your main file, with Sound mySound = new Sound("path_to_sound"); Where you replace path_to_sound with your path. I believe one of the supported formats is .wav. Then you can just play the sound whenever you want to with mySound.play();, and whenever you do it will be played from the beginning.
Regarding your implementation of using spacebar to play / replay the audio, I believe it is better if you try to work with the given code in order to understand how it works.

Playing Sound From .jar File

I have looked at countless different StackOverflow answers as well as answers from other sites, but none of the solutions have fixed my problem. I cannot for the life of me get my .wav file to play.
Here is my code:
Sound class:
public class Sound {
/**
* Static file paths for each sound.
*/
public static String stepSound = "/resources/step.wav";
/**
* Audio input stream for this sound.
*/
private AudioInputStream audioInputStream;
/**
* Audio clip for this sound.
*/
private Clip clip;
/* -- Constructor -- */
/**
* Creates a new sound at the specified file path.
*
* #param path File path to sound file
*/
public Sound(String path) {
// Get the audio from the file
try {
// Convert the file path string to a URL
URL sound = getClass().getResource(path);
System.out.println(sound);
// Get audio input stream from the file
audioInputStream = AudioSystem.getAudioInputStream(sound);
// Get clip resource
clip = AudioSystem.getClip();
// Open clip from audio input stream
clip.open(audioInputStream);
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}
}
/* -- Method -- */
/**
* Play the sound.
*/
public void play() {
// Stop clip if it's already running
if (clip.isRunning())
stop();
// Rewind clip to beginning
clip.setFramePosition(0);
// Play clip
clip.start();
}
/**
* Stop the sound.
*/
public void stop() {
clip.stop();
}
}
Constructor call that leads to error:
// Play step sound
new Sound(Sound.stepSound).play();
I know this isn't the first time a problem like this has been asked or answered on this website, but I've been trying other solutions for hours at this point and all I've found is pain and frustration. I can post more code if needed. Thanks in advance.
EDIT: I have unpacked the .jar file and confirmed that the file is indeed there. The problem is that the URL ends up being null, and so a NullPointerException is thrown.
EDIT #2: Added more code in case there's another problem.

How to get SQLite 'VACUUM' Progress

Is there a way to get the progress of sqlite 'VACUUM'?I am using this line of code here in Java:
connection1.createStatement().executeUpdate("VACUUM");
The User(MySelf & I) has to wait from some seconds to some minutes,i know that the actual .db file is being overriten with the help of a journal file that is created through the execution of the command.
Can i get an estimation using JAVA IO or something?Thanks for help..
No.
The SQLite C API has a progress handler, but it's probably not exposed by your Java driver, and the vacuum processing is implemented with a different mechanism that does not report the progress anyway.
You could try to look at the current size of the database file and of any temporary files, but it is practically impossible to get the name of the latter.
I found the answer to my question.So i know the size of the actual .db file and i wrote a Service in javaFX which calculates every 50 miliseconds the size of .db-journal file.So i check very frequently the size of journal file to see how of % is builded based on actual .db file:
package windows;
import java.io.File;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
/** Get the progress of Vacuum Operation */
public class VacuumProgress extends Service<Void> {
File basicFile;
File journalFile;
/**
* Starts the Vacuum Progress Service
*
* #param basicFile
* #param journalFile
*/
public void start(File basicFile, File journalFile) {
this.basicFile = basicFile;
this.journalFile = journalFile;
reset();
start();
}
#Override
protected Task<Void> createTask() {
return new Task<Void>() {
#Override
protected Void call() throws Exception {
System.out.println("Started...");
long bfL = basicFile.length();
while (!journalFile.exists()) {
Thread.sleep(50);
System.out.println("Journal File not yet Created!");
}
long jfL = journalFile.length();
while (jfL <= bfL) {
updateProgress(jfL = journalFile.length(), bfL);
Thread.sleep(50);
}
System.out.println("Exited Vacuum Progress Service");
return null;
}
};
}
}

what should be the value passed in function to connect to my google drive using java program?

I got following code from google developers site:
package javaapplication24;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpResponse;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import java.io.IOException;
import java.io.InputStream;
// ...
public class NewClass {
// ...
/**
* Print a file's metadata.
*
* #param args
* #param service Drive API service instance.
* #param fileId ID of the file to print metadata for.
*/
private static void printFile(Drive service, String fileId) {
try {
File file = service.files().get(fileId).execute();
System.out.println("Title: " + file.getTitle());
System.out.println("Description: " + file.getDescription());
System.out.println("MIME type: " + file.getMimeType());
} catch (IOException e) {
System.out.println("An error occured: " + e);
}
}
/**
* Download a file's content.
*
* #param service Drive API service instance.
* #param file Drive File instance.
* #return InputStream containing the file's content if successful,
* {#code null} otherwise.
*/
private static InputStream downloadFile(File file, Drive service) {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
HttpResponse resp =
service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl()))
.execute();
return resp.getContent();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
// ...
}
I know i need to write a main function with this and call the functions printFile and DownloadFile but I am not getting what is to be passed in function as variable service?
You have to understand how it works first!
In order to download or print details about your files, you need to authenticate your app from your google account with right scope(permissions like readonly, modify/delete and so on).
Once authentication is done. You will get access token to access the data.
This is a small fragment of code that says what the Drive service means
/**
* Build and return an authorized Drive client service.
* #return an authorized Drive client service
* #throws IOException
*/
public static Drive getDriveService() throws IOException {
Credential credential = authorize();
return new Drive.Builder(
HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
Head on to this link to learn more about it
https://developers.google.com/drive/web/quickstart/java
Note: It would be unnecessarily long answer, if i copy paste the complete code here

How can I intercept the audio stream on an android device?

Let's suppose that we have the following scenario: something is playing on an android device (an mp3 par example, but it could be anything that use the audio part of an android device). From an application (android application :) ), I would like to intercept the audio stream to analyze it, to record it, etc. From this application (let's say "the analyzer") I don't want to start an mp3 or something, all I want is to have access to the audio stream of android.
Any advice is appreciated, it could a Java or C++ solution.
http://developer.android.com/reference/android/media/MediaRecorder.html
public class AudioRecorder {
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD
* card).
*/
public AudioRecorder(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath()
+ path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if (!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state
+ ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
Consider using the AudioPlaybackCapture API that was introduced in Android 10 if you want to get the audio stream for a particular app.

Categories