I recorded some audio files that must be played from java. I did it about half-year ago. Now, when I add files, they sound as if being sped-up with higher pitch. Old files sound normally, new ones don't. I suppose there is something that has to be changed in audio parameters. What could it be?
That's the code I'm using to play .wav files:
AudioInputStream result1 = AudioSystem.getAudioInputStream(new File("/home/nikkka/Desktop/alphabet/result.wav"));
DataLine.Info info = new DataLine.Info(Clip.class, result1.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(result1);
clip.start();
At the risk of stating the obvious ...
If the old file still play fine and the new ones don't, then it must be something different about the way that you recorded the new files.
It doesn't sound like the real problem is anything to do with programming, let alone Java.
of course. but the thing is, i recorded the old files with settings i don't actually remember.
My suggestion is to fiddle with the settings until you can once again record files that play properly.
Related
I am currently programming a game and now I also want to add sound. My current method works fine but I am not happy with it.
new Sound(new Resource().readAndGetStream("small_click.wav")).play();
This line of code reads the file small_click.wav whenever it is getting executed. But I think it is not very efficient to always read the resource file when it's needed.
So what I want to do now is caching a sound in a variable or something to not have to load the sound from file again. But I also want to create a new object from the sound, so I can play it mutiple times and it overlaps in the speakers.
I can't find a way to do this. I already tried to use Threads but.. this code works without any threads.
If you want to know, here is the code of the Sound class:
public Sound(InputStream audioSrc) {
try {
InputStream bufferedIn = new BufferedInputStream(audioSrc);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(bufferedIn);
clip = AudioSystem.getClip();
clip.open(audioStream);
} catch {
...exception handling...
}
}
public void play() {
clip.setFramePosition(0);
clip.start();
}
And If you want to know what the "new Resource().readAndGetStream()" does:
It basically loads a resource and returns an InputStream of that resource with getResourceAsStream().
With the Sound class that you have, you can easily create a "cache". For example, create an array of type Sound[] soundCache and execute the first part of the code line you gave in your example.
soundCache[0] = new Sound(new Resource().readAndGetStream("small_click.wav"));
You could even consider making constants to correspond to each sound.
final int SMALL_CLICK = 0;
Then, when it is time to play the sound, execute your play function.
soundCache[SMALL_CLICK].play();
Going from here to having concurrent playbacks of a given sound is quite a bit more involved. If continuing to work with Clip as your basis, I don't know of any way to get overlapping playbacks of the same sound resource except by making and managing as many copies of the Clip as you might want to allow to be heard at once.
When faced with this coding challenge, I ended up writing my own library, AudioCue. It is available on Github, and has a very permissive license.
The basic concept is to store the audio data in an array of signed PCM floats, and manage the concurrent playback by having multiple "cursors" that can independently iterate through the PCM data and feed it to a SourceDataLine.
These cursors can be managed in real time. You can change the rate at which they travel through the data and scale the volume level of the data, allowing frequency and volume changes.
I did my best to keep the API as similar to a Clip as practical, so that the class would be easy to use for coders familiar with Java's Clip.
Feel free to examine the code for ideas/examples or make use of this library in your project.
How can I save an opened audio file with changed volume?
I trying this:
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("some_file.wav"));
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
gainControl.setValue(-30.0f); // Reduce volume by 10 decibels.
File file = new File("new.wav");
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, file);
But this is saving an empty file.
I think your best bet will be to take the bytes from the AudioInputStream and convert them to PCM values, then multiply the PCM values by a factor that matches -10 db. I don't know what that factor would be. Then convert back to bytes and write that.
The first code example in the tutorial Using Files and Format Converters shows a while loop where the conversions would take place, at the comment: "// Here, do something useful with the audio..."
The prior tutorial on the Audio Trail: "Processing Audio with Controls" might also be helpful, but the built-in controls are limited and dependent on the host computer and OS. For example, if you want to change volumes (put in a fade-in or fade-out) the control lines probably don't work very well due to the granularity being tied to the size of the audio buffer. So I recommend the advice of the final paragraphs of the "Processing Audio with Controls" tutorial, the section "Manipulating the Audio Data Directly".
Suppose I have a sound file that I wish to play in this manner:
Start from the 0:00 mark.
When the sound file ends, replay from the 0:30.00 mark.
Essentially, I wish for the song to play from 0:00 to 0:30, then loop from 0:30 to the end.
How do you do this?
Usually, when playing Audio Files, I use AudioClip.
AudioClip audio = Applet.newAudioClip( this.getClass().getResource( "..." ) );
audio.loop();
It's because of bad experiences with loading the audio file when the project is packed into a .jar file. If the method you recommend uses another class, I would still be more than happy to listen. However, if you've encountered the same problem as I have and know how to fix it, please do tell me.
You might use a Clip for this, or if the clip is too large, feed the bytes directly to a SourceDataLine.
I was looking into the Java sound API and noticed that it allows us to play audio files. I have two questions. Given an audio file, how can we use javax.sound to play the audio file at any random location. Moreover, does javax.sound convert audio files to text files containing their lyrics?
"to play the audio file at any random location":
When you are creating an AudioInputStream object you can just give it the bytestream starting at the position at which you want to start like so:
audioInputStream = new AudioInputStream( byteArrayInputStream, audioFormat,
audioData.length/audioFormat.getFrameSize());
This is from the complete example-code at:
http://www.developer.com/java/other/article.php/1565671/Java-Sound-An-Introduction.htm
To your second question: There exist several speech-recognition packages but as far as i know they do a poor job at parsing music because there is too much "noise".
Given an audio file, how can we use javax.sound to play the audio file ..
If you'd read the JavaSound info page you'd have seen source that can play a sound.
..at any random location?
Clip also provides setMicrosecondPosition(long) & setFramePosition(int). Feed a random number to either, and you're set to go.
Snippet that gets the wanted length from the total length :
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream( new File( "file.wav") );
clip.open( ais );
long currentPos = clip.getMicrosecondPosition(); // get the current position of clip
After these steps, is there a way that i can make up a new audio file, without data conversion (keeping audio data same) but it's length equal to the currentPos ?
i.e cutting up the audio file and reducing it's size to currentPos
Clips aren't the most useful for manipulating audio data. I think you have to load your sound file into a byte array and work off of that.
To hear it, you can wrap the raw audio array in a TargetDataLine implementation. The TDL implementation gives you hooks to start or stop where-ever you like.
If you want to save the sliced files, you probably know about using AudioSystem.write() method which takes an AudioInputStream as one of the arguments. The TDL can be wrapped in an AIS for these writes.
If there is an easier way to do it, I'm looking forward to reading about it!
lots of audio editing tools can do this sort of thing. Try goldwave.