I'm porting a small (<10 classes) C++ project to Java. The project manipulates sound files, and in C++ does this using libsndfile. The code includes stuff like:
const int channels = audioFileInfo.channels;
...
sf_readf_double( audioFile, inputBuffer, MAX_ECHO );
...
sf_writef_double( outputAudioFile, ¤tAudioBuffer[WINDOW_SIZE * channels], SEGMENTATION_LENGTH );
In Java, what's the best way to manipulate sound files on a low level? I'm talking about stuff like normalizing, adding echoes etc.
Progress Report
After a bit of digging I've found javax.sound.sampled, which looks like it might do the job.
Edit 2 On closer inspection, it won't work (or at least not in any usable way), since it relies on the com.sun.sound
package.
Edit 3 On even more inspection, and experimentation, the com.sun.sound
and sun.misc
packages are released under the GNU GPLv2, and I've downloaded them into my project. Having renamed javax.sound.sampled
to imp.javax.sound.sampled
, the project compiles, and I can create AudioFileFormat
objects without any exceptions being thrown, yet. I haven't had a chance to play around much yet but I'll keep you updated.
Edit 4 Ok, Some things appear to work with javax.sound.sampled, others do not. For example, calls such as:
AudioInputStream stream = AudioSystem.getAudioInputStream(waveFile));
do not work, however I can get around this by doing:
WaveFileReader wfr = new WaveFileReader();
AudioInputStream stream = wfr.getAudioInputStream(waveFile);
In general, calls to things like AudioSystem.getAudioFileTypes()
return empty lists. I can delve into the packages and see it's something to do with providers, but I'm at a loss how to remedy this. Having got my stream
object it does report its encoding etc. correctly, which is encouraging.
My big problem at the moment is creating a Clip object. This needs to be created with a Line object, which would normally come from AudioSystem. Can anyone think of a way around this?
libsndfile can be compiled for Android using the Native Development Kit. Once you have the library compiled for Android, you should be able to use JNI to access it from Java.
If you can port libsndfile using the NDK, why not just use the NDK to port your C++ code directly and not worry about porting it to java?
Why don't you just keep this code in C++ and invoke it in your Java through JNI ?