Saving changed clip into file - java

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".

Related

How do I convert heapbytebuffer to "File"?

I have a heapbytebuffer in a variable "myByteBuffer" that represents an audio wav that I want to playback. I see that AudioInputStream is a way to play files using AudioSystem.getAudioInputStream(soundFile). Since it accepts a "File", how can I convert the heapbytebuffer I have to a "File"?
Don't use the File overload unless you have (or want to save) a physical file. Just take your data and wrap it in an InputStream:
AudioSystem.getAudioInputStream(new ByteArrayInputStream(myByteBuffer.array()))
This assumes you're using the full buffer. If not, you can slice out the part you're using as necessary. See here for details.

JAVA: Controlling volume of an audioinputstream

I use in a java code a wav file that I load into an AudioInputStream using AudioInputStream ais = AudioSystem.getAudioInputStream("file.wav")
Once I have done that, I wish to basically pick up the n amount of seconds at the end (let's say the 5 last seconds) and "fade out" the volume (FloatControl.Type.MASTER_GAIN??).
Once done I could transfert my audiostreaminput back into a wav file using: AudioSystem.write(ais, Type.WAVE, file_output);
the result is a same wav file but with the last 5 seconds fading out (volume decreasing).
Any idea on how to do this? I tried changing the ais into bytes[], or a sourcedataline... but didn't find what I wanted, as most examples are about changing volume of an audio "in-play" (I also saw things around using Clip which also seems to be dealing an audio file in-play)
Many thanks everyone
Start by turning the sound into a byte array. Then turn the bytes into samples: you'll need to find a tutorial specifically for this, it's a little involved in Java (http://www.jsresources.org/ is a good resource). Samples are the direct representation of the sound wave.
To decrease the volume, multiply all the samples by something less than 1, and then save them back to a byte array. To fade out you'll need to multiply the last n samples by a decreasing function. Then write out the file with the proper WAV headers.
These are just a few pointers for a complex process, hopefully they will send you in the right direction.

Using the java.sound API

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.

Why audio files sound different?

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.

making a new audio file without data conversion but of shorter length

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.

Categories

Resources