2016-09-04 23 views
15

Tôi đang cố gắng trích xuất mảng biên độ từ tệp âm thanh (tệp WAV). Tôi sẽ sử dụng mảng biên độ này để biên độ âm mưu so với đồ thị thời gian cho tệp wav đã cho. Tôi có thể vẽ đồ thị bản thân mình nhưng không biết làm thế nào để trích xuất biên độ từ tập tin âm thanh (wav) nhất định trong java?Trích xuất mảng biên độ từ tệp wav bằng cách sử dụng JAVA

Trả lời

4

Đây là lớp trợ giúp mà bạn có thể sử dụng. Phương pháp getSampleInt() là những gì bạn cần để có được biên độ:

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

Nó cũng có thể chơi các tập tin để bạn có thể kiểm tra nó, nhưng chỉ có 8 bit, hoặc các tập tin 16bit. Đối với các trường hợp khác, bạn chỉ có thể đọc chúng.

Ngoài ra, hãy xem these diagrams để xem tệp WAV bao gồm và hiểu rõ hơn về những gì lớp này làm.

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; 
    } 
} 
+0

sự khác nhau giữa kích thước mẫu 8 bit, 16 bit ... tôi đang sử dụng âm thanh 24 bit ... làm cách nào để sửa đổi mã cho âm thanh 24 bit? và nó cũng cung cấp cho dòng không có ngoại lệ .... và xin vui lòng bạn có thể giải thích các mã chi tiết ... i am mới này api âm thanh và điều âm thanh ... PS: Cảm ơn rất nhiều – Jason

+0

@ Jason nó là một chất lượng. Bạn nên đọc những gì WAV là, trước khi cố gắng đọc nó :) Google, hoặc đăng một câu hỏi khác ở đây. Tôi đã xóa một vài dòng thừa từ ví dụ của tôi - có thể đọc bất kỳ tệp WAV nào, nhưng không thử chơi bất kỳ thứ gì khác ngoài 8bit hoặc 16bit. Java không hỗ trợ điều này, bạn chỉ có thể đọc chúng và vẽ đồ họa theo ý muốn. –

+0

cùng một mã không thể được sử dụng cho tập tin mp3? ... coz các định dạng khác nhau – Jason

0

Tôi đã thử mã của bạn và với một vài thay đổi nhỏ mà nó tạo ra kết quả. Có gì sai với dữ liệu mã đặt ra?

tôi thay đổi những dòng sau:

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

Điều thứ hai tôi đã thay đổi là:

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

Trong phương pháp chính của bạn, vì bạn chỉ được in ra các địa chỉ của arary. Sau khi những thay đổi đó, mã đưa ra một mảng có giá trị, dường như tương quan với dữ liệu mong muốn.

bạn thiếu gì, hoặc bạn mong đợi gì về dữ liệu? Bạn có thể làm rõ câu hỏi thêm một chút không?

+0

điều tôi muốn làm là vẽ đồ thị giữa biên độ và thời gian cho tệp wav cụ thể .... thời gian liên quan đến thời điểm/thời gian hiện tại của tệp wav âm thanh đang được phát ..... vì vậy làm thế nào tôi có thể trích xuất biên độ từ tập tin wav tại những khoảnh khắc khác nhau? PS: Xin vui lòng bỏ qua mã của tôi .... tôi không nghĩ rằng nó có thể là chính xác – Jason

+0

thực sự, mã đã làm việc khá tốt. Tại sao bạn xóa nó? Bạn đã nhận được một mảng chứa số nguyên. Đó là những giá trị biên độ. thời gian được biết vì tỷ lệ lấy mẫu. bạn có thể giải nén nó từ đối tượng audioformat. của nó trong hz, nói rằng bạn có 44100, có nghĩa là 44100 giá trị của mảng là 1 giây. thats cách bạn tính toán thời gian cho một mẫu –

+0

Tôi đã thử nghiệm mã mà bạn đã đăng trước đó với PCM_SIGNED 44100.0 Hz, 16 bit, âm thanh nổi, 4 byte/khung, tệp WAV nhỏ của Windows (ir_begin.wav), nó đã cho tôi giá trị chính xác –

Các vấn đề liên quan