I want to read wav files in Java and I am going to classify them with K-means.
How can I read wav files in Java and assign them into an array or something like that(you can suggest ideas for it) to classify them?
EDIT: I want to use APIs for reading wav files and for K-means.
The official Java Sound Programmer Guide walks through reading and writing audio files.
This article by A Greensted: Reading and Writing Wav Files in java should be helpful. The WavFile class is very useful and it can be tweaked to return the entire data array instead of buffered fragments.
Equivalent to matlab's wavread function:
http://web.archive.org/web/20120531113946/http://www.builogic.com/java/javasound-read-write.html
You could read the sound files using javax sound library and FileInputStream
(found a nice example here)
and treat the wave files as a vector of bits (0,1) or bytes.. using multiple sequence alignment (Wiki) create a distance matrix between every stream of bits/bytes, and from there, the clustering should be straight forward.
The Problem is, that this method is very sensitive to noise, etc, but it is worth a shot...
Not sure if this will help someone. Java JDK already provides AudioSystem class.
I used this as part of my tests to check generated WAV properties,
AudioFileFormat audioFileFormat = AudioSystem.getAudioFileFormat(new File(response.get()));
assertEquals(1, audioFileFormat.getFormat().getChannels());
assertEquals(8000.0, audioFileFormat.getFormat().getSampleRate(), 0.0f);
assertEquals(8, audioFileFormat.getFormat().getSampleSizeInBits());
Related
I'm trying to record from the microphone to a wav file as per this example. At the same time, I need to be able to test for input level/volume and send an alert if it's too low. I've tried what's described in this link and seems to work ok.
The issue comes when trying to record and read bytes at the same time using one TargetDataLine (bytes read for monitoring are being skipped for recording and vice-versa.
Another thing is that these are long processes (hours probably) so memory usage should be considered.
How should I proceed here? Any way to clone TargetDataLine? Can I buffer a number of bytes while writing them with AudioSystem.write()? Is there any other way to write to a .wav file without filling the system memory?
Thanks!
If you are using a TargetDataLine for capturing audio similar to the example given in the Java Tutorials, then you have access to a byte array called "data". You can loop through this array to test the volume level before outputting it.
To do the volume testing, you will have to convert the bytes to some sort of sensible PCM data. For example, if the format is 16-bit stereo little-endian, you might take two bytes and assemble to either a signed short or a signed, normalized float, and then test.
I apologize for not looking more closely at your examples before posting my "solution".
I'm going to suggest that you extend InputStream, making a customized version that also performs the volume test. Override the 'read' method so that it obtains the byte that it returns from the code you have that tests the volume. You'll have to modify the volume-testing code to work on a per-byte basis and to pass through the required byte.
You should then be able to use this extended InputStream as an argument when you create the AudioInputStream for the output-to-wav stage.
I've used this approach to save audio successfully via two data sources: once from an array that is populated beforehand, once from a streaming audio mix passing through a "mixer" I wrote to combine audio data sources. The latter would be more like what you need to do. I haven't done it from a microphone source, though. But the same approach should work, as far as I can tell.
I have a server written in Java, that in a single request, gets a whole file from the client. The file is passed to the server as a list of bytes, and is finally represented in the java server as a byte array.
Is there some standard way / standard library that could tell whether a file represented by a byte array is a valid zip file?
Files are typically identified using magic numbers in the beginning of the file.
To make an educated guess about a given file Java has built-in method of detecting some file types: Files.probeContentType. Plus, there are various third party libraries: simplemagic or Apache Tika (which supports more than only magic numbers).
But content detection alone won't tell you whether the file is valid. For that, you'd need something that actually knows how to read Zip files, such as Java's ZipFile.
If you want to standard way to implement for this process, you can use serialization API.For that use following articles that found myself while searching about this topic.
Article 1 - javaworld
Article 2 - developer.com
Check Zip4j library. It is really easy to use and the ZipFile class has a isValidZipFile() method
The easiest way is to check the "PK" magic at the beginning of the byte array.
Something like this:
"PK".equals(new String(array, 0,2))
I'd like to modify the audio input stream, the stream that would come
from my microphone.
I have looked through the java.sound package API, but did not entirely understand it,
nor how to modify direct sound input.
Does anyone here know how to do that, or know an API that is capable of doing it?
You want a mixture of things:
The Java Sound system: http://www.oracle.com/technetwork/java/index-139508.html
A trail for it: http://docs.oracle.com/javase/tutorial/sound/index.html
Using audio controls: http://docs.oracle.com/javase/1.5.0/docs/guide/sound/programmer_guide/chapter6.html (part of a wider set of documentation)
If you are able to give more information about what you want to do to the audio stream, it's likely we'll be able to give you more specific advice.
I have been using mp3spi, tritonus and JLayer to process mp3 files. I am stuck up at one point where I need mp3 input stream / mp3 audio signal as floating point array. Please help!
Thanks
Have you tried using or sub-classing java.io.DataInputStream? Perhaps the readFloat() method is what you are looking for.
I want to change the volume of an audio file
and save the new file using java.sound.sampled.
I tried to use the mixer to create a source line
from the file given and a target line to the new file.
So that I can change the mixer settings to change the volume.
But the sound is being played to the system speaker.
Am I thinking along correct way or not?
Is there any other way to record a file from a line?
The code is available here
A solution I got is www.jsresources.org/examples/AmplitudeConverter.html.
But can the same be done within java.sound.sampled
without using external libraries.
To change the volume, if you don't use a "Control" (see the Java Sound Tutorials), there is the option of directly modifying the samples themselves.
In your innermost loop, convert the bytes in the innermost buffer into a sample (if it is WAV 16-bit encoding, then you need to put the two bytes together to make the single SHORT value), then multiply that value by a float that ranges from 0 to 1, where 0 is the quietest and 1 leaves the sound at full volume. Then take the result and break it back down into two bytes and pass it along.
Do you need the code to do this? There are several other posts here where folks convert from bytes to INTs or Float and back.
Hmmm. This question is pretty old. Well maybe my answer will help someone new to the same problem.