While playing an audio file (.wav) I want, if I resort to Ctrl+C, to stop the playback and save part of the audio file in a file called "file2.wav".
Here's the thread I'd like to add to my code.
Unfortunately it doesn't work at all.
class myThread extends Thread{
public void run(){
try {
PipedOutputStream poStream = new PipedOutputStream();
PipedInputStream piStream = new PipedInputStream();
poStream.connect(piStream);
File cutaudioFile = new File ("file2.wav");
AudioInputStream ais =
new AudioInputStream(piStream,
AudioFileFormat.Type.WAVE,
cutaudioFile);
poStream.write(ais,AudioFileFormat.Type.WAVE,cutaudioFile);
}catch (Exception e){
e.printStackTrace();
}
} // end run
} // end myThread
This should be basically what you want. It uses a shutdown hook.
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.Clip;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class CtrlCAudio
{
public static void main(String[] args) throws LineUnavailableException, UnsupportedAudioFileException, IOException
{
final File inputAudio = new File(args[0]);
final File outputAudio = new File(args[1]);
// First, we get the format of the input file
final AudioFileFormat.Type fileType = AudioSystem.getAudioFileFormat(inputAudio).getType();
// Then, we get a clip for playing the audio.
final Clip c = AudioSystem.getClip();
// We get a stream for playing the input file.
AudioInputStream ais = AudioSystem.getAudioInputStream(inputAudio);
// We use the clip to open (but not start) the input stream
c.open(ais);
// We get the format of the audio codec (not the file format we got above)
final AudioFormat audioFormat = ais.getFormat();
// We add a shutdown hook, an anonymous inner class.
Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
// We're now in the hook, which means the program is shutting down.
// You would need to use better exception handling in a production application.
try
{
// Stop the audio clip.
c.stop();
// Create a new input stream, with the duration set to the frame count we reached. Note that we use the previously determined audio format
AudioInputStream startStream = new AudioInputStream(new FileInputStream(inputAudio), audioFormat, c.getLongFramePosition());
// Write it out to the output file, using the same file type.
AudioSystem.write(startStream, fileType, outputAudio);
}
catch(IOException e)
{
e.printStackTrace();
}
}
});
// After setting up the hook, we start the clip.
c.start();
}
}
Related
I keep getting an exception saying IllegalArgrumentException, it says audio data < 0 and that there is something wrong on line 17. But I see nothing wrong. I want to be able to play audio.
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import javax.sound.sampled.*;
public class sound {
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException{
Scanner scanner = new Scanner(System.in);
File file = new File("[ONTIVA.COM] YEAY Sound Effect-HQ.wav");
AudioInputStream audioStream = AudioSystem.getAudioInputStream(file);
Clip clip = AudioSystem.getClip();
clip.open(audioStream);
String response = scanner.next();
}
}
I'm making game extension to play some sounds. The sounds may be triggered at random times, which means that the same sound may be triggered twice with very little time apart. In this case, the sound should start playing even though it is already playing (if that makes sense).
I'm using a Clip to play the sound. This means that I have to "rewind" the clip before playing it. It seems, since it's the same clip, that it stops playing before re-starting. What I want is for it to continue playing, and play the same clip "on top" of the previos one. See this example:
import java.io.File;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class JavaApplication {
public static void main(String[] args) throws Exception {
File file = new File(JavaApplication.class.getResource("1.wav").getPath());
AudioInputStream inputStream = AudioSystem.getAudioInputStream(file);
Clip clip = AudioSystem.getClip();
clip.open(inputStream);
clip.setFramePosition(0);
clip.start(); // The sound is 300 ms long
Thread.sleep(150); // Let it play for 150 ms
clip.setFramePosition(0); // Attempt to start it from the beginning, without stopping it
clip.start();
Thread.sleep(1000);
}
}
Have you tried creating a duplicate object when you need it and destroy it when it's finished? A new Clip object or just copy the original and get it to play along with it.
Clip temp = clip;
temp.start(); // The sound is 300 ms long
Thread.sleep(150); // Let it play for 150 ms
temp = null;
Just a suggestion, you could also try using Clip[] arrays to handle a few clips playing at different times.
You need to create two AudioInputStream instances. No need to use multi thread exlicitly in your code. Hop it will help. Thanks.
import java.io.File;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class JavaApplication {
public static void main(String[] args) throws Exception {
File file = new File(JavaApplication.class.getResource("1.wav").getPath());
AudioInputStream inputStream1 = AudioSystem.getAudioInputStream(file);
AudioInputStream inputStream2 = AudioSystem.getAudioInputStream(file);
Clip clip = AudioSystem.getClip();
clip.open(inputStream1);
clip.setFramePosition(0);
clip.start();
// Clip is 2000 ms long. let it play for 1000 ms
Thread.sleep(1000);
Clip clip2 = AudioSystem.getClip();
clip2.open(inputStream2);
clip2.setFramePosition(0);
clip2.start();
Thread.sleep(2000);
}
}
Found a solution: Read the raw bytes of the sound, and create a inputstream from the data each time I play the sound. This enables me to play the same sound file "on top of itself" without loading it from disk more than once.
package com.mysite.javaapplication;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class JavaApplication {
private static void playSoundBytes(byte[] data) throws Exception {
AudioInputStream inputStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(data));
AudioFormat format = inputStream.getFormat();
Clip clip = AudioSystem.getClip();
clip.open(inputStream);
clip.setFramePosition(0);
clip.start();
}
private static byte[] getResourceAsBytes(String name, int bufferSize) throws IOException {
InputStream stream = JavaApplication.class.getResourceAsStream(name);
byte buffer[] = new byte[bufferSize];
int b, i = 0;
while ((b = stream.read()) != -1) {
try {
buffer[i++] = (byte) b;
} catch (IndexOutOfBoundsException e) {
throw new IOException("Buffer of " + bufferSize + " bytes is too small to read resource \"" + name + "\"");
}
}
byte data[] = new byte[i + 1];
while (i >= 0) {
data[i] = buffer[i];
i--;
}
return data;
}
public static void main(String[] args) throws Exception {
byte[] soundData = getResourceAsBytes("/1.wav", 1000*1000);
playSoundBytes(soundData);
Thread.sleep(1000);
playSoundBytes(soundData);
Thread.sleep(2000);
}
}
I am trying to record a 16khz mono-channel .wav file by using this code
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;
public class Main {
public static void main(String[] args) {
System.out.println("Say what you see..");
try {
AudioFormat format = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED, 16000, 8, 1, 4, 16000,
false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if (!AudioSystem.isLineSupported(info))
System.out.println("Line not Supported");
final TargetDataLine targetLine = (TargetDataLine) AudioSystem
.getLine(info);
targetLine.open();
System.out.println("Recording");
targetLine.start();
Thread thread = new Thread() {
#Override
public void run() {
AudioInputStream audioStream = new AudioInputStream(
targetLine);
File audioFile = new File("record.wav");
try {
AudioSystem.write(audioStream,
AudioFileFormat.Type.WAVE, audioFile);
} catch (IOException ioe) {
ioe.printStackTrace();
}
System.out.println("stopped recording");
}
};
thread.start();
Thread.sleep(5000);
targetLine.stop();
targetLine.close();
System.out.println("Done");
} catch (Exception e) {
e.printStackTrace();
}
}
}
When I run it I always get this error:
Line not Supported
java.lang.IllegalArgumentException: No line matching interface TargetDataLine supporting format PCM_SIGNED 16000.0 Hz, 8 bit, mono, 4 bytes/frame, is supported.at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:476)at Main.main(Main.java:29)
ps: I tested it many times with different parameters for the AudioFormat It only worked when I tried these parameters which is stereo and 44.1khz
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,44100,16,2,4,44100,false);
You must specify an AudioFormat that matches one of the formats supported by the TargetDataLine.
For example the microphone on my Mac supports:
'unknown sample rate' means the sample rate doesn't matter.
The main difference I see here is that you are specifying 4 bytes per frame, for 8 bit mono this should be 1 byte per frame.
Simple GUI application for playing sound clips after user selects one with a radio button and pushes the play button. After clean and build, execution from the JAR file results in no sound being played when a clip is selected and the play button is pushed.
Conditions: NetBeans IDE, sounds play successfully in the IDE pathed to the package, path to .wav files in JAR is correct, files are in the executable JAR in the correct directory, uses 2 classes: one for the GUI and a .wav handler class (both work successfully in the IDE. More details in screen shots. I am thinking that there should be a getResource() method call in the Player calss but I don't know how to write it.
The code snippet used to call the resource from within the GUI class. The base is new Player("whateverthefilepathis").start(). (this works fine in the IDE, so no issue there):
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
if (jRadioButton1.isSelected()){
URL file = QuotesButtonUI.class.getResource("/my/sounds/fear_converted.wav");
new Player (file.getFile()).start();
}
else if (jRadioButton2.isSelected()){
URL file = QuotesButtonUI.class.getResource("/my/sounds/initiated_converted.wav");
new Player (file.getFile()).start();
}
This is the Player class used to process the .wav. Within the GUI class, I am using the new Player().start() call. I am thinking that there should be a getResource() call in the Player class but I don't know for sure.
package my.quotesbutton;
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.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Player extends Thread {
private String filename;
private Position curPosition;
private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb
enum Position {
LEFT, RIGHT, NORMAL
};
public Player(String wavfile) {
filename = wavfile;
curPosition = Position.NORMAL;
}
public Player(String wavfile, Position p) {
filename = wavfile;
curPosition = p;
}
public void run() {
File soundFile = new File(filename);
if (!soundFile.exists()) {
System.err.println("Wave file not found: " + filename);
return;
}
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline
.getControl(FloatControl.Type.PAN);
if (curPosition == Position.RIGHT)
pan.setValue(1.0f);
else if (curPosition == Position.LEFT)
pan.setValue(-1.0f);
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
You can't access anything inside a jar file using the java.io.File API, simply because items inside a jar are not files.
You need indeed, as you suspected, to use a getResource() method (or getResourceAsStream()): http://docs.oracle.com/javase/tutorial/deployment/webstart/retrievingResources.html
That may look counterintuitive at first, but getResource() works with files as well as jars (or even remote located resources in case of a webapp, as in the linked tutorial), the ClassLoader will deal with the dirty details how the resource is physically accessed. In short: never use the File API for resources - resources should only be accessed using the resource API.
I have two .3gp (or .wav) audio files that I have saved from the user's microphone. How can I concatenate these two audio files together in code into a single file? Thanks.
combining two wav files:
import java.io.File;
import java.io.IOException;
import java.io.SequenceInputStream;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
public class WavAppender {
public static void main(String[] args) {
String wavFile1 = "D:\\wav1.wav";
String wavFile2 = "D:\\wav2.wav";
try {
AudioInputStream clip1 = AudioSystem.getAudioInputStream(new File(wavFile1));
AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(wavFile2));
AudioInputStream appendedFiles =
new AudioInputStream(
new SequenceInputStream(clip1, clip2),
clip1.getFormat(),
clip1.getFrameLength() + clip2.getFrameLength());
AudioSystem.write(appendedFiles,
AudioFileFormat.Type.WAVE,
new File("D:\\wavAppended.wav"));
} catch (Exception e) {
e.printStackTrace();
}
}
}