• Java extract amplitude array from recorded wave


    转载自:http://ganeshtiwaridotcomdotnp.blogspot.com/2011/12/java-extract-amplitude-array-from.html


    Extract amplitude array from recorded/saved wav : From File , AudioInputStream , ByteArray of File or ByteArrayInputStream - working java source code example

    import java.io.ByteArrayInputStream;  
     import java.io.File;  
     import java.io.FileInputStream;  
     import java.io.FileOutputStream;  
     import java.io.IOException;  
     import javax.sound.sampled.AudioFileFormat;  
     import javax.sound.sampled.AudioFormat;  
     import javax.sound.sampled.AudioInputStream;  
     import javax.sound.sampled.AudioSystem;  
     import javax.sound.sampled.UnsupportedAudioFileException;  
     /**  
      * saving and extracting amplitude data from wavefile byteArray  
      *   
      * @author Ganesh Tiwari  
      */  
     public class WaveData {  
          private byte[] arrFile;  
          private byte[] audioBytes;  
          private int[] audioData;  
          private ByteArrayInputStream bis;  
          private AudioInputStream audioInputStream;  
          private AudioFormat format;  
          private double durationSec;  
          private double durationMSec;  
          public WaveData() {  
          }  
          public int[] extractAmplitudeFromFile(File wavFile) {  
               try {  
                    // create file input stream  
                    FileInputStream fis = new FileInputStream(wavFile);  
                    // create bytearray from file  
                    arrFile = new byte[(int) wavFile.length()];  
                    fis.read(arrFile);  
               } catch (Exception e) {  
                    System.out.println("SomeException : " + e.toString());  
               }  
               return extractAmplitudeFromFileByteArray(arrFile);  
          }  
          public int[] extractAmplitudeFromFileByteArray(byte[] arrFile) {  
               // System.out.println("File : "+wavFile+""+arrFile.length);  
               bis = new ByteArrayInputStream(arrFile);  
               return extractAmplitudeFromFileByteArrayInputStream(bis);  
          }  
          /**  
           * for extracting amplitude array the format we are using :16bit, 22khz, 1  
           * channel, littleEndian,  
           *   
           * @return PCM audioData  
           * @throws Exception  
           */  
          public int[] extractAmplitudeFromFileByteArrayInputStream(ByteArrayInputStream bis) {  
               try {  
                    audioInputStream = AudioSystem.getAudioInputStream(bis);  
               } catch (UnsupportedAudioFileException e) {  
                    System.out.println("unsupported file type, during extract amplitude");  
                    e.printStackTrace();  
               } catch (IOException e) {  
                    System.out.println("IOException during extracting amplitude");  
                    e.printStackTrace();  
               }  
               // float milliseconds = (long) ((audioInputStream.getFrameLength() *  
               // 1000) / audioInputStream.getFormat().getFrameRate());  
               // durationSec = milliseconds / 1000.0;  
               return extractAmplitudeDataFromAudioInputStream(audioInputStream);  
          }  
          public int[] extractAmplitudeDataFromAudioInputStream(AudioInputStream audioInputStream) {  
               format = audioInputStream.getFormat();  
               audioBytes = new byte[(int) (audioInputStream.getFrameLength() * format.getFrameSize())];  
               // calculate durations  
               durationMSec = (long) ((audioInputStream.getFrameLength() * 1000) / audioInputStream.getFormat().getFrameRate());  
               durationSec = durationMSec / 1000.0;  
               // System.out.println("The current signal has duration "+durationSec+" Sec");  
               try {  
                    audioInputStream.read(audioBytes);  
               } catch (IOException e) {  
                    System.out.println("IOException during reading audioBytes");  
                    e.printStackTrace();  
               }  
               return extractAmplitudeDataFromAmplitudeByteArray(format, audioBytes);  
          }  
          public int[] extractAmplitudeDataFromAmplitudeByteArray(AudioFormat format, byte[] audioBytes) {  
               // convert  
               // TODO: calculate duration here  
               audioData = null;  
               if (format.getSampleSizeInBits() == 16) {  
                    int nlengthInSamples = audioBytes.length / 2;  
                    audioData = new int[nlengthInSamples];  
                    if (format.isBigEndian()) {  
                         for (int i = 0; i < nlengthInSamples; i++) {  
                              /* First byte is MSB (high order) */  
                              int MSB = audioBytes[2 * i];  
                              /* Second byte is LSB (low order) */  
                              int LSB = audioBytes[2 * i + 1];  
                              audioData[i] = MSB << 8 | (255 & LSB);  
                         }  
                    } else {  
                         for (int i = 0; i < nlengthInSamples; i++) {  
                              /* First byte is LSB (low order) */  
                              int LSB = audioBytes[2 * i];  
                              /* Second byte is MSB (high order) */  
                              int MSB = audioBytes[2 * i + 1];  
                              audioData[i] = MSB << 8 | (255 & LSB);  
                         }  
                    }  
               } else if (format.getSampleSizeInBits() == 8) {  
                    int nlengthInSamples = audioBytes.length;  
                    audioData = new int[nlengthInSamples];  
                    if (format.getEncoding().toString().startsWith("PCM_SIGN")) {  
                         // PCM_SIGNED  
                         for (int i = 0; i < audioBytes.length; i++) {  
                              audioData[i] = audioBytes[i];  
                         }  
                    } else {  
                         // PCM_UNSIGNED  
                         for (int i = 0; i < audioBytes.length; i++) {  
                              audioData[i] = audioBytes[i] - 128;  
                         }  
                    }  
               }// end of if..else  
                    // System.out.println("PCM Returned===============" +  
                    // audioData.length);  
               return audioData;  
          }  
          public byte[] getAudioBytes() {  
               return audioBytes;  
          }  
          public double getDurationSec() {  
               return durationSec;  
          }  
          public double getDurationMiliSec() {  
               return durationMSec;  
          }  
          public int[] getAudioData() {  
               return audioData;  
          }  
          public AudioFormat getFormat() {  
               return format;  
          }  
     }  

    留言:

    Think I found a bug for 8 bit unsigned samples in the code above.

    Java regards a byte-variable as a signed variable, so we can't just subtract 128 for all sample-values. For "negative" values we must instead add 128, I think.

    E.g. the sampled unsigned value 10000000 (128 unsigned) should mean that we are in the middle of the value-range. It should actually mean 0, but java sees it as -128, and if we subtract 128 we'll get -256, which isn't what we want at all.

    And the "highest" sample-value possible with 8 bits, 11111111, means -1 to java if it's in a byte-variable. We'd get the value -129 here with the old method, but we would expect 127.

    For all "positive" values 00000000 - 01111111 it works fine to subtract 128 as before, so something like this would work better:

    // PCM_UNSIGNED
    for (int i = 0; i < audioBytes.length; i++)
    {
    if (audioBytes[i] >= 0)
    _audioData[i] = audioBytes[i] - 128;
    else
    _audioData[i] = audioBytes[i] + 128;
    }

    (Or e.g. you could "shift" the byte-value into an int-variable before subtracting 128.)

  • 相关阅读:
    A Look Inside Presentation Controllers
    iOS用户数据安全:Keychain、Touch ID以及1Password
    iOS开发UI篇—UITableView全面解析
    iOS 上的相机捕捉
    iOS UIScrollView
    ViewController类中得方法和属性的用途
    ios 中__bridge,__bridge_transfer和__bridge_retained详解
    __weak如何实现对象值自动设置为nil
    iOS开发UI篇—UIWindow简单介绍
    iOS:App启动过程详解
  • 原文地址:https://www.cnblogs.com/passedbylove/p/11888799.html
Copyright © 2020-2023  润新知