Playing audio on Raspberry pi with java - java

Hi i have this code here
import java.io.File;
import java.io.IOException;
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 Playmusic implements Runnable {
public static void main(String[] args){
Thread t = new Thread(new Playmusic());
t.start();
}
#Override
public void run() {
AudioInputStream audioIn;
try {
audioIn = AudioSystem.getAudioInputStream(new File("test.wav"));
Clip clip;
clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
Thread.sleep(clip.getMicrosecondLength()/1000);
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException e1) {
e1.printStackTrace();
}
}
}
to play a sound on the raspberry. But when i run it, it doesn't produce any output.
I've tested it on both Windows and Linux systems where it works.
The program does notice the file though since it sleeps for the whole duration of the sound and doesn't give me any Runtime exception.
It also can't be the speaker that's causing the problem because i can play the sound with aplay test.wav and it gives me an output. I wanted to use the JavaFX library but it seems to be removed on the cut down java version of resbian.

This has nothing to do with Java or Raspbian... Check the RPi configuration sudo raspi-config, and ensure you are having your audio output well configured between HDMI or Jack Out. That should do the trick...

Related

Play sound in GUI program

I have been experimenting with Java Swing using a GUI and have hit a wall. I am trying to play a sound using Java Sound. Ultimately, I want to push a button and the sound plays. I have tried a lot of combinations but none seem to work. Here is the latest code I tried and I code and it reports:
Error: could not find or load main class.
I am not seeing why:
package net.codejava.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;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* This is an example program that demonstrates how to play back an audio file
* using the SourceDataLine in Java Sound API.
* #author www.codejava.net
*
*/
public class AudioPlayerExample2 {
// size of the byte buffer used to read/write the audio stream
private static final int BUFFER_SIZE = 4096;
/**
* Play a given audio file.
* #param audioFilePath Path of the audio file.
*/
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(SourceDataLine.class, format);
SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);
audioLine.open(format);
audioLine.start();
System.out.println("Playback started.");
byte[] bytesBuffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = audioStream.read(bytesBuffer)) != -1) {
audioLine.write(bytesBuffer, 0, bytesRead);
}
audioLine.drain();
audioLine.close();
audioStream.close();
System.out.println("Playback completed.");
} 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 static void main(String[] args) {
String audioFilePath = "https://codehs.com/uploads/1981fc4b1d2e4123e9cbe7ab8cc1962a";
AudioPlayerExample2 player = new AudioPlayerExample2();
player.play(audioFilePath);
}
}
I made a couple small changes to the tutorial code example you posted, and the program worked perfectly well.
Here are my changes:
(1) Replaced "File audioFile = new File(audioFilePath);" with the following:
URL audioFile = null;
try {
audioFile = new URL(audioFilePath);
} catch (MalformedURLException e) {
e.printStackTrace();
}
(2) Added the following line to the module-info file (required if you are using Java 9 or higher):
requires java.desktop;
My package setting is slightly different, but I assume you know how to properly set up packages. Your class is in the file folder specified by the package statement, yes?
The error being cited: "could not find or load main class" indicates that something is going wrong with how the code is being invoked rather than a problem with the audio part of the code. What version of Java are you using? What IDE? What is the command you are issuing to execute the program? FWIW, my setup that successfully executed this code has an up-to-date Eclipse IDE running Java 11.
Nam Ha Minh's tutorials at codejava.net usually are quite good. I think he is one of the more reliable tutorial writers out there.

Program works in Eclipse but when I export to runnable JAR it doesnt. FileNotFoundException

I tried to make a runnable JAR, but for some reason I couldn't get my game to play. I did some research and ran it through my command prompt to try to find the error and I got this below. So obviously I know the issue I just need to fix it. I have the audio file in my res folder which is in my src. So if it is already in the program I can't figure out why I would get this error. Thoughts?
Exception in thread "main" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Unknown Source)
at java.desktop/javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
at builder.AudioPlayer.playMenuSound(AudioPlayer.java:20)
at builder.Game.<init>(Game.java:56)
at builder.Game.main(Game.java:61)
package builder;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioPlayer {
private static Clip play;
public static void playMenuSound()
{
try {
//AudioInputStream menuSound = AudioSystem.getAudioInputStream(new File("src/res/introSong.wav")); //Take in audio from res folder
AudioInputStream menuSound = AudioSystem.getAudioInputStream(AudioPlayer.class.getClassLoader().getResourceAsStream("introSong.wav"));
play = AudioSystem.getClip(); //
play.open(menuSound); //Play the sound
FloatControl volume = (FloatControl) play.getControl(FloatControl.Type.MASTER_GAIN); //Get control of volume
volume.setValue(1.0f); //0.0 - 1.0 volume
play.loop(Clip.LOOP_CONTINUOUSLY); //Loop once clip is over
}catch (LineUnavailableException | IOException | UnsupportedAudioFileException e){
e.printStackTrace();
}
}
public static void playGameSound()
{
try {
//AudioInputStream gameSound = AudioSystem.getAudioInputStream(new File("src/res/inGame.wav")); //Take in audio from res folder
AudioInputStream gameSound = AudioSystem.getAudioInputStream(AudioPlayer.class.getClassLoader().getResourceAsStream("inGame.wav"));
play = AudioSystem.getClip(); //
play.open(gameSound); //Play the sound
FloatControl volume = (FloatControl) play.getControl(FloatControl.Type.MASTER_GAIN); //Get control of volume
volume.setValue(0.5f); //0.0 - 1.0 volume
play.loop(Clip.LOOP_CONTINUOUSLY); //Loop once clip is over
}catch (LineUnavailableException | IOException | UnsupportedAudioFileException e){
e.printStackTrace();
}
}
public static void stopMusic()
{
play.close(); //Stop music
}
}
The problem in your code is where you're trying to instantiate your file with a new reference, here:
AudioInputStream gameSound = AudioSystem.getAudioInputStream(new File("src/res/inGame.wav"));
Instead of doing that, you need to get your file as a resource using a ClassLoader, since it is located inside the resource (res) folder.
Here is how your code should look like:
AudioInputStream gameSound = AudioSystem.getAudioInputStream(AudioPlayer.class.getClassLoader().getResourceAsStream("inGame.wav"));
Same should be done in with your introSong.wav in the playMenuSound() method. The code should look something like
AudioInputStream gameSound = AudioSystem.getAudioInputStream(AudioPlayer.class.getClassLoader().getResourceAsStream("introSong.wav"));
I really hope this solves your problem.
I have had success with the following form for setting up Clips. Perhaps it will work for you.
URL url = this.getClass().getResource("audio/" + filename);
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
The method getResource returns a URL. The method getResourceAsStream returns an InputStream. A URL works as a way to address a file within a jar.
In this example, the file in which the code resides is a parent to the folder "/audio" and the audio resource is in the "/audio" folder.
The following form works for me if you desire to call the loader as a static method.
URL url = AudioPlayer.class.getResource("audio/" + filename);

Audio file plays in Eclipse IDE; but NOT as JAR file

The audio file that I am using is found here: http://www.orangefreesounds.com/loud-alarm-clock-sound/
This is what my file structure looks like in my Eclipse IDE:
The audio file plays perfectly fine when I run it in my IDE, but not when I export it as a JAR file. I have already checked and found that the audio file is inside the JAR file.
I am using the terminal command java -jar Sandbox.jar & to run the JAR file. The program seems to be able to find the file (since it is not throwing an IOException), but does not seem to be able to perform playback.
Why is this problem happening and how can I fix it?
Weird Update
Okay, so actually, the JAR file is able to play the audio file when run in cmd or PowerShell on Windows 8.1, but not in the terminal of Ubuntu 14.04 for some reason. This whole time, I have been trying to run the JAR file in Ubuntu 14.04.
Weird Update #2
I have confirmed the issue of the JAR files only working on a Windows 8.1 system. Both of the code snippets in this question DO NOT WORK, while both of MadProgrammer's solutions work.
Minimal, Complete, and Verifiable example (does NOT work on Windows or Ubuntu)
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;
public class Sandbox
{
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
URL url = Sandbox.class.getResource("/sound-effects/alarmSoundClip.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
}
}
Attempted Solution #1 (does NOT work on Windows or Ubuntu)
One attempted solution (as suggested by Andrew Thompson) was to write this.getClass().getResource( ... ) instead of Sandbox.class.getResource( ... ):
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;
public class Sandbox
{
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
new Sandbox();
}
public Sandbox() throws UnsupportedAudioFileException, IOException, LineUnavailableException
{
URL url = this.getClass().getResource("/sound-effects/alarmSoundClip.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
}
}
Adding clip.drain() after clip.start() seems to have worked okay for me (IDE and command line both with and without &)
import java.io.IOException;
import java.net.URL;
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.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Sandbox {
public static void main(String[] args) {
try {
URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.start();
System.out.println("Drain...");
clip.drain();
System.out.println("...Drained");
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException exp) {
exp.printStackTrace();
}
}
}
Now, having said that, I have found drain a little unreliable in the past, especially when there are multiple sounds playing in which case I tend to use a LineListener
For example...
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
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 Sandbox {
protected static final Object LOCK = new Object();
public static void main(String[] args) {
try {
URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
AudioFormat af = ais.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, af);
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
clip.addLineListener(new LineListener() {
#Override
public void update(LineEvent event) {
System.out.println(event.getType());
if (event.getType() == LineEvent.Type.STOP) {
synchronized (LOCK) {
LOCK.notify();
}
}
}
});
clip.start();
synchronized (LOCK) {
LOCK.wait();
}
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException exp) {
exp.printStackTrace();
}
}
}

Playing Sound in Java [duplicate]

This question already has answers here:
Access restriction error on my Java Code
(2 answers)
Closed 8 years ago.
Hello I'm trying to play a sound in java the code looks like this:
public void playSound(String sound) {
try {
InputStream in = new FileInputStream(new File(sound));
AudioStream audio = new AudioStream(in);
AudioPlayer.player.start(audio);
} catch (Exception e) {}
}
I imported sun.audio*; however get an error:
Access restriction: The type 'AudioPlayer' is not API (restriction on
required library 'C:\Program Files\Java\jre7\lib\rt.jar')
The following program plays a 16-bit wav sound from eclipse if we use javax.sound.
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
import javax.swing.*;
// To play sound using Clip, the process need to be alive.
// Hence, we use a Swing application.
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);
// You could also get the sound file with a URL
File soundFile = new File("C:/Users/niklas/workspace/assets/Sound/sound.wav");
try ( // Open an audio input stream.
AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
// 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();
}
}

error playing sound java (No line matching interface Clip supporting format)

We are trying to integrated sound in one of our project, my team members don't get this error, and I get it on two different machines.
Stack trace:
Exception in thread "SoundPlayer" java.lang.IllegalArgumentException: No line matching interface Clip supporting format PCM_SIGNED 16000.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian, and buffers of 11129272 to 11129272 bytes is supported.
at javax.sound.sampled.AudioSystem.getLine(Unknown Source)
at sound.Music.run(Music.java:86)
at java.lang.Thread.run(Unknown Source)
Code:
package 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.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Music implements LineListener, Runnable
{
private File soundFile;
private Thread thread;
private static Music player;
private Music audio;
private Clip clip;
public Music()
{
}
public void playSiren(String musicFileName)
{
Music p = getPlayer();
p.playSirenFile(musicFileName);
}
private void playSirenFile(String musicFileName)
{
this.soundFile = new File("Music/"+musicFileName+".wav");
thread = new Thread(this);
thread.setName("SoundPlayer");
thread.start();
}
public void run()
{
try
{
AudioInputStream stream = AudioSystem.getAudioInputStream(this.soundFile);
AudioFormat format = stream.getFormat();
/**
* we can't yet open the device for ALAW/ULAW playback, convert
* ALAW/ULAW to PCM
*/
if ((format.getEncoding() == AudioFormat.Encoding.ULAW) || (format.getEncoding() == AudioFormat.Encoding.ALAW))
{
AudioFormat tmp = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
format.getSampleRate(),
format.getSampleSizeInBits() * 2, format.getChannels(),
format.getFrameSize() * 2, format.getFrameRate(), true);
stream = AudioSystem.getAudioInputStream(tmp, stream);
format = tmp;
}
DataLine.Info info = new DataLine.Info(Clip.class, stream
.getFormat(), ((int) stream.getFrameLength() * format
.getFrameSize()));
clip = (Clip) AudioSystem.getLine(info);
clip.addLineListener(this);
clip.open(stream);
clip.start();
try
{
thread.sleep(99);
}
catch (Exception e)
{
}
while (clip.isActive() && thread != null)
{
try
{
thread.sleep(99);
}
catch (Exception e)
{
break;
}
}
clip.loop(99999999);
}
catch (UnsupportedAudioFileException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (LineUnavailableException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Music getPlayer()
{
if (player == null)
{
player = new Music();
}
return player;
}
public void update(LineEvent event)
{
}
public void stopClip()
{
clip.stop();
}
public void closeClip()
{
clip.close();
}
public void startClip()
{
clip.start();
}
public void volume(float volume)
{
/*
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
gainControl.setValue(-50.0f); // Reduce volume IN DECIBELS
clip.start();
*/
}
}
We call this class from domainController with
audio = new Music();
audio.playSiren("stillAliveDecent");
does Anyone have an idea how this exception can be resolved?
I tried reinstalling my editor software (Eclipse) but to no avail.
thanks allot in advance.
Edit
We just tried switching the sound file. We tried running it with much smaller file. this now works, but once we switch back to the larger .wav file (10+MB) I get the exception again.
Only using smaller files is not really an option as we would like to use some self made songs which are quite long.
Edit 2
I'm quite sure it isn't a corrupted wav. we recompiled it, even used another wave of similar length and size, and i'm still the only one getting this error.
some extra requested info:
OS: Windows 7 64bit Ultimate
JDK: 1.6.0_22
Edit 3
After some wave creating and playing we have come to the conclusion that for some reason I can't play wave's larger than 2MB.
Still why aren't my teammates affected by this?
I was experiencing this same problem on a raspberry pi. It would play the first 5 files just fine, then I'd get the error. It turned out that I was not closing the clip when I needed to.
Clip clip = AudioSystem.getClip();
clip.addLineListener(event -> {
if(LineEvent.Type.STOP.equals(event.getType())) {
clip.close();
}
});
ByteArrayInputStream audioBytes = new ByteArrayInputStream(SOUNDS.get(file));
AudioInputStream inputStream = AudioSystem.getAudioInputStream(audioBytes);
clip.open(inputStream);
clip.start();
After adding the line listener and closing the clip when it stopped, the errors went away.
You can actually play sound above 40 mb, if needed, thats how far i went :p, the problem is mostly eclipse, and to be more exact its the .metadata folder in your workspace i think its like a small plugin that only gets uploaded half of the time, so the problem lies with your editor and not the code, the code above is working perfectly since i could play songs without any trouble. Make sure your paths are correct, and try to get a correct version of the .metadata and you should be fine. A friend of mine had the same problem, and i gave him my copy of the workspace and .metadata and it worked perfectly.

Categories