Looping audio and inputdialog box cancel - java

Im trying to get a backtrack on my JOptionPane game working. I have the code for the audio to loop. But when a user clicks cancel on an inputdialog box it exits the game but does not close the audio thread.
I need something to kill the audio thread when this happens.
I have tried other methods of playing the audio .wav file. But when user hit cancel it still plays. Have tried using JFrames and disposing of the frame, but this doesn't dispose the audio thread too.
URL urlfog = theFog.class.getClassLoader().getResource("thefog.wav");
AudioInputStream audioStreamfog = AudioSystem.getAudioInputStream(urlfog);
AudioFormat formatfog = audioStreamfog.getFormat();
DataLine.Info infofog = new DataLine.Info(Clip.class, formatfog);
Clip audioClipfog = (Clip) AudioSystem.getLine(infofog);
audioClipfog.open(audioStreamfog);
audioClipfog.loop(audioClipfog.LOOP_CONTINUOUSLY);
String name;
do {
name = (String) JOptionPane.showInputDialog(null,"Hello what is your name?","The Fog",JOptionPane.INFORMATION_MESSAGE,icon1,null,"");
}
while (name.equalsIgnoreCase(""));
No error messages just the audio is still playing after a cancel of the program.

String name;
do {
name = (String) JOptionPane.showInputDialog(null, "Hello what is your name?", "The Fog", JOptionPane.INFORMATION_MESSAGE, icon1, null, "");
if ((name == null)) {
audioClipfog.stop();
System.exit(0);
}
}
while (name.equalsIgnoreCase(""));

Related

How to play several audio clips (not at the same time) in an applet?

I need help playing music in my java code. Right now I'm using the mouseClicked method in my JApplet, and each time I click on a certain location music, from a wav file is supposed to play. But when I run the applet, only the first object I click on will play, after nothing else will play and I cannot exit the applet (I have to force quit)
I have already tried using the clip.stop() method after it has played, and after using that no sound plays at all.
this is my code in my class for playing music that's attached to my JApplet.
public void playMusic()
{
try{
File file = new File("island_music_x.wav");
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(file));
clip.start();
Thread.sleep(clip.getMicrosecondLength());
}
catch(Exception e)
{
System.err.println(e.getMessage());
}
}
this is code for an object that is supposed to be clicked in my applet to play music.
xpos5 = me.getX();
ypos5 = me.getY();
if
(xpos5 > rect5xco && xpos5 < rect5xco+rect5width && ypos5 >
rect5yco && ypos5 < rect5yco+rect5height)
rect5Clicked = true;
else
rect5Clicked = false;
when it is set to true I have code to play the music
if
(rect5Clicked == true)
{
try{
m5.playMusic5();}
catch (Exception e)
{}
}
When I click on an object, music is supposed to play, which occurs, however; I should be able to click on other objects after the first one and play music as well. But, the music only plays the first time. I am also unable to exit the appletviewer.
Any help would be great thank you!!

Java play AAC encoded audio ( JAAD decoder )

I have struggled with playing aac encoded audio files with Java a while now.
We had a group project at the end of our first semester and wanted to have a background music and few soundeffects in there.
At the end we used WAV files, as we couldn't get the AAC's to play.
This weekend I gave it another try and searched along again, and have got a working code searched together from different sites, but nowhere was a complete working solution.
For a more comfortable usage in future projects I made me a small library for aac playback.
As it was hard to find the working solution, I wanted to share it with you, in the hope some one having the same problem in the future will have it a bit easier.
The following code is a snippet from the lib I wrote. You can have a look onto the whole lib on GitLab at
Java AAC-Player.
This lib/solution uses the aac decoder JAAD.
The player I wrote around the JAAD library is available as Maven artifact:
<dependency>
<groupId>com.gitlab.9lukas5</groupId>
<artifactId>jaad</artifactId>
<!--
check latest version on https://search.maven.org
or try the latest tag you find in git
-->
</dependency>
public static void play(File[] files)
{
// local vars
byte[] b; // array for the actual audio Data during the playback
AudioTrack track; // track we are playing atm
AudioFormat af; // the track's format
SourceDataLine line; // the line we'll use the get our audio to the speaker's
Decoder dec; // decoder to get the audio bytes
Frame frame; //
SampleBuffer buf; //
int currentTrack; // index of current track from playlist
MP4Container cont; // container to open the current track with
Movie movie; // and get the content from the container
try
{
// for-next loop to play each titel from the playlist once
for (currentTrack = 0; currentTrack < files.length; currentTrack++)
{
cont = new MP4Container(new RandomAccessFile(files[currentTrack], "r")); // open titel with random access
movie = cont.getMovie(); // get content from container,
List<Track> content = movie.getTracks();
if (content.isEmpty()) // check if container HAS content
throw new Exception ("insert error message here"); // if so,
track = (AudioTrack) movie.getTracks().get(0); // grab first track and set the audioformat
af = new AudioFormat(track.getSampleRate(), track.getSampleSize(), track.getChannelCount(), true, true);
line = AudioSystem.getSourceDataLine(af); // get a DataLine from the AudioSystem
line.open(); // open and
line.start(); // start it
dec = new Decoder(track.getDecoderSpecificInfo());
buf = new SampleBuffer();
while(track.hasMoreFrames()) // while we have frames left
{
frame = track.readNextFrame(); // read next frame,
dec.decodeFrame(frame.getData(), buf); // decode it and put into the buffer
b = buf.getData(); // write the frame data from the buffer to our byte-array
line.write(b, 0, b.length); // and from there write the byte array into our open AudioSystem DataLine
while (paused) // check if we should pause
{
Thread.sleep(500); // if yes, stay half a second
if (Thread.interrupted()) // check if we should stop possibly
{
line.close(); // if yes, close line and
return; // exit thread
}
}
if (Thread.interrupted()) // if not in pause, still check on each frame if we should
{ // stop. If so
line.close(); // close line and
return; // exit thread
}
}
line.close(); // after titel is over, close line
if (loop) // if we should loop current titel, set currentTrack -1,
currentTrack--; // as on bottom of for-next it get's +1 and so the same titel get's played again
else if (repeat && (currentTrack == files.length -1)) // else check if we are at the end of the playlist
currentTrack = -1; // and should repeat the whole list. If so, set currentTrack -1, so it get's 0 on for-next bottom
}
}
catch (LineUnavailableException | IOException | InterruptedException e)
{
e.printStackTrace();
}
}

My 1:30 minute long WAV file is only playing for three seconds

I'm trying to play a .wav file in this code, but for some reason it only plays the minute-long song for about three seconds. Does anyone have any ideas why?
private void btnPlayActionPerformed(java.awt.event.ActionEvent evt) {
try {
JFXPanel j = new JFXPanel();
String uri = new File("04_Kensington_Chump (1).wav").toURI().toString();
new MediaPlayer(new Media(uri)).play();
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex);
}
}
You are creating a new media player in the method, and just leaving it there without storing it in a variable you can later access. This causes the garbage collector to pick it up.
Create a list to store all your media players so the garbage collector doesn't destroy them, and that should fix the problem
MediaPlayer player = new MediaPlayer(new Media(uri));
player.play();
someList.add(player);
Then periodically clean the list when players are done playing the audio

Recording multiple MIDI tracks

I am writing an application that records MIDI data from a keyboard.
It should be able to record multiple tracks and store them in one MIDI file.
It is controlled with three buttons - "record", "stop recording" and "write to a MIDI file".
I followed this tutorial on StackOverflow to write the recording method.
Everything was going well until I tried to record a second track. track#2 is recorded, but it is placed in the sequence behind the track#1 i.e. they donĀ“t play simultaneously in the MIDI file and if I try to play only track#2, there is a lot of blank space in the beginning of it.
I read that I have to use
Sequencer.setTickPosition(0);
which I did, but without any effect.
Here are parts of the code:
The user presses "record" button:
sequencer.open();
sequencer.setSequence(mySequence);
newTrack = mySequence.createTrack();
sequencer.setTickPosition(0);
sequencer.recordEnable(newTrack, -1);
sequencer.startRecording();
When "stop recording" button is pressed:
sequencer.stopRecording();
sequencer.recordDisable(newTrack);
And finally when "write to MIDI file" button is pressed:
Sequence tmp = sequencer.getSequence();
MidiSystem.write(tmp, 1, new File("Sequence.MID"));
//*******************************************************************
Here is my full code:
private MidiDevice inputDevice // Selected from a combo box
private Sequencer sequencer = MidiSystem.getSequencer();
private Transmitter transmitter = inputDevice.getTransmitter();
private Receiver receiver = sequencer.getReceiver();
transmitter.setReceiver(receiver);
private Sequence seq = new Sequence(Sequence.PPQ,24);
private Track newTrack;
/*
.
Buttons added
.
*/
public void actionPerformed( ActionEvent e ){
Object source = e.getSource();
if (source == record){
sequencer.open();
sequencer.setSequence(seq);
newTrack = seq.createTrack();
sequencer.setTickPosition(0);
sequencer.recordEnable(newTrack, -1);
sequencer.startRecording();
}
//*********************************************************************
if (source == stop){
sequencer.stopRecording();
sequencer.recordDisable(newTrack);
}
//******************************************************************
if(source == write){
Sequence tmp = sequencer.getSequence();
MidiSystem.write(tmp, 1, new File("MyMidiFile1.mid"));
}
}
Thanks in advance for any advice!

How to have lyrics highlighted as mp3 file plays (like karaoke) using JLayer

I have created a media player in Java using JLayer, and it accepts mp3 files. I also have the lyrics to a specific song appear once the user plays that song, but now I want to somehow highlight or change the text color of the lyrics as they are heard in the song (like karaoke). I only need to do this for one song - and I'll have the lyrics already implemented in my program. I have already searched for how to do this but can't seem to find exactly what I'm looking for. Below I added the code to my class that plays the music file.
public class PlayMusic {
/**
* Global variables. FileInputStream obtains input bytes from a file system
* and reads streas of raw bytes. BufferedInputStream adds functionality
* to the fis, and creates an internal buffer array.
*/
private String filename;
private Player player;
private boolean canResume;
private boolean valid;
private int total;
private int stopped;
FileInputStream fis;
BufferedInputStream bis;
/**
* Constructor the takes in the path of the mp3 file to be played.
* #param filename - path of the mp3 file
*/
public PlayMusic(String filename) {
this.filename = filename;
this.canResume = false;
this.valid = false;
this.total = 0;
this.stopped = 0;
this.fis = null;
this.bis = null;
}
/**
* Function called to stop a song altogether as opposed to pausing.
*/
public void close() {
if (player != null)
player.close();
stopped = 0;
fis = null;
bis = null;
player = null;
canResume = false;
}
/**
* Function called to pause a song. Fis.available() is a method that returns
* the number of remaining bytes that can be read from the input stream.
*/
public void pause(){
try {
if (fis!=null)
stopped = fis.available();
if (player!= null)
player.close();
fis = null;
bis = null;
player = null;
if(valid)
canResume = true;
} catch (IOException e) {
}
}
/**
* Function called when we want to resume a song from where it left off
* after being paused.
*/
public void resume()
{
if(!canResume)
return;
if(play(total-stopped))
canResume = false;
}
/**
* Function called to play the song and keep track of where in the song the
* user presses stop in order for the resume button to work properly. Fis.skip
* skips over and discards pos bytes of data from fis.
* #param pos - The position of the song in which we want to resume play
* #return
*/
public boolean play(int pos) {
valid = true;
canResume = false;
try {
fis = new FileInputStream(filename);
total = fis.available();
if(pos> -1)
fis.skip(pos);
bis = new BufferedInputStream(fis);
player = new Player(bis);
}
catch (Exception e) {
System.out.println("Problem playing file " + filename);
System.out.println(e);
}
/**
* Run the play button in a new thread so the music plays in the background.
*/
new Thread() {
public void run() {
try { player.play(); }
catch (Exception e) { System.out.println(e); valid = false; }
}
}.start();
return valid;
}
}
You won't be able to detect what words are being sung in the song (with ease at least), but if you have the lyrics of the song in a file, and you have the sound file of the song, then to me it sounds like you could just add more info to that lyrics file to create a map of when the words of the lyrics are being sung in the song.
For example, if I was to do this with the song Jingle Bells, I may have a tab separated file that contains the lyrics, where one line is one word, with a begin and end time relative to the start of the song in milliseconds.
jingle 0 1000
bells 1001 1500
jingle 1501 2500
bells 2501 3000
... and so on
Edit for explaining how to code up keeping track of how long a song has been playing.
Two methods to create an instance variable called say, totalTimeSongHasBeenPlaying
I'm not sure how you have abstracted out playing your sound files, but say that you abstracted that out to a Sound class, then you could have three methods, sound.soundStarted, sound.soundStopped, sound.soundRestarted, then at the start of playing the sound you can call soundStarted which could grab a System.nanoTime or a System.currentTimeMillis and on soundStopped, you could grab it again and take the difference and add it to totalTimeSongHasBeenPlaying, and on soundRestart you could set totalTimeSongHasBeenPlaying to zero.
Do some math against frame position the sound you are currently playing is versus how many frames is in a second for that file. I don't know the exact libraries for JLayer, it's been a while since I used it, but that method should also tell you how far along in the file you are.
After that, the Sound class could also then have a method such as currentWordBeingSung(), which looks at totalTimeSongHasBeenPlaying, and uses the lookup table you created off the lyrics file during construction and returns the specific word uniquely (may be duplicates). Your gui when you create it, say your JLyricsViewer, can hold an instance to your Sound object and you can use a SwingTimer to repaint it every 50 ms or so, where in your paintComponent method it looks at currentWordBeingSung().

Categories

Resources