I am trying to extract amplitude array from an audio file(WAV file). I will be using this amplitude array to plot amplitude vs time graph for the given wav file. I am able to plot the graph myself but does not know how to extract the amplitude from given audio(wav) file in java?
Here is a helper class that you can use. The getSampleInt()
method is what you need to get the amplitude:
File file = ...;
WavFile wav = new WavFile(file);
int amplitudeExample = wav.getSampleInt(140); // 140th amplitude value.
for (int i = 0; i < wav.getFramesCount(); i++) {
int amplitude = wav.getSampleInt(i);
// Plot.
}
It also can play files so that you can test it, but only 8bit, or 16bit files. For other cases you can only read them.
Also, please look at these diagrams to see what WAV files consist of and better understand what this class does.
public class WaveFile {
public final int NOT_SPECIFIED = AudioSystem.NOT_SPECIFIED; // -1
public final int INT_SIZE = 4;
private int sampleSize = NOT_SPECIFIED;
private long framesCount = NOT_SPECIFIED;
private int sampleRate = NOT_SPECIFIED;
private int channelsNum;
private byte[] data; // wav bytes
private AudioInputStream ais;
private AudioFormat af;
private Clip clip;
private boolean canPlay;
public WaveFile(File file) throws UnsupportedAudioFileException, IOException {
if (!file.exists()) {
throw new FileNotFoundException(file.getAbsolutePath());
}
ais = AudioSystem.getAudioInputStream(file);
af = ais.getFormat();
framesCount = ais.getFrameLength();
sampleRate = (int) af.getSampleRate();
sampleSize = af.getSampleSizeInBits() / 8;
channelsNum = af.getChannels();
long dataLength = framesCount * af.getSampleSizeInBits() * af.getChannels() / 8;
data = new byte[(int) dataLength];
ais.read(data);
AudioInputStream aisForPlay = AudioSystem.getAudioInputStream(file);
try {
clip = AudioSystem.getClip();
clip.open(aisForPlay);
clip.setFramePosition(0);
canPlay = true;
} catch (LineUnavailableException e) {
canPlay = false;
System.out.println("I can play only 8bit and 16bit music.");
}
}
public boolean isCanPlay() {
return canPlay;
}
public void play() {
clip.start();
}
public void stop() {
clip.stop();
}
public AudioFormat getAudioFormat() {
return af;
}
public int getSampleSize() {
return sampleSize;
}
public double getDurationTime() {
return getFramesCount() / getAudioFormat().getFrameRate();
}
public long getFramesCount() {
return framesCount;
}
/**
* Returns sample (amplitude value). Note that in case of stereo samples
* go one after another. I.e. 0 - first sample of left channel, 1 - first
* sample of the right channel, 2 - second sample of the left channel, 3 -
* second sample of the rigth channel, etc.
*/
public int getSampleInt(int sampleNumber) {
if (sampleNumber < 0 || sampleNumber >= data.length / sampleSize) {
throw new IllegalArgumentException(
"sample number can't be < 0 or >= data.length/"
+ sampleSize);
}
byte[] sampleBytes = new byte[4]; //4byte = int
for (int i = 0; i < sampleSize; i++) {
sampleBytes[i] = data[sampleNumber * sampleSize * channelsNum + i];
}
int sample = ByteBuffer.wrap(sampleBytes)
.order(ByteOrder.LITTLE_ENDIAN).getInt();
return sample;
}
public int getSampleRate() {
return sampleRate;
}
public Clip getClip() {
return clip;
}
}
I tried your code and with a few minor changes it created a result. Whats wrong with the data the code puts out?
I Changed the following lines:
// create file input stream
DataInputStream fis = new DataInputStream(new FileInputStream(wavFile));
// create byte array from file
arrFile = new byte[(int) wavFile.length()];
fis.readFully(arrFile); // make sure you always read the full file, you did not check its return value, so you might be missing some data
The second thing I changed was:
System.out.println(Arrays.toString(s.extractAmplitudeFromFile(f)));
In your Main method, since you were only printing out the adress of the arary. After those changes the code put out an array that had values, that seemed to correlate with the desired data.
what excatly are you missing, or what do you expect of the data? Could you please clarify the question a bit more?
来源:https://stackoverflow.com/questions/39313634/extract-amplitude-array-from-a-wav-file-using-java