使用JAVA从wav文件中提取振幅数组

我试图从音频文件(WAV文件)中提取振幅数组。 我将使用此振幅数组来绘制给定wav文件的幅度与时间关系图。 我能够自己绘制图形,但不知道如何从java中的给定音频(wav)文件中提取幅度?

这是一个可以使用的辅助类。 getSampleInt()方法是获取幅度所需的方法:

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

它还可以播放文件,以便您可以测试它,但只能测试8位或16位文件。 对于其他情况,您只能阅读它们。

另外,请查看这些图表以查看WAV文件的组成,并更好地了解此类的function。

 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. Ie 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; } } 

我尝试了您的代码,并通过一些小的更改创建了一个结果。 代码输出的数据有什么问题?

我改变了以下几行:

 // 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 

我改变的第二件事是:

 System.out.println(Arrays.toString(s.extractAmplitudeFromFile(f))); 

在您的Main方法中,因为您只打印出了arary的地址。 在这些更改之后,代码推出了一个具有值的数组,这些数据似乎与所需数据相关。

你遗憾的是什么,或者你对数据的期望是什么? 你能再详细澄清一下这个问题吗?