【问题标题】:Wav file convert to byte array in javaWav文件在java中转换为字节数组
【发布时间】:2012-05-01 11:53:02
【问题描述】:

我的项目是“阿塞拜疆语音的语音识别”。我必须编写一个将wav 文件转换为字节数组的程序。

如何将音频文件转换为字节[]?

【问题讨论】:

    标签: java arrays audio javasound wave


    【解决方案1】:

    基本上如第一个答案中的 sn-p 所述,但不是 BufferedInputStream 而是使用 AudioSystem.getAudioInputStream(File) 来获取 InputStream

    使用从AudioSystem 获得的音频流将确保去除标题,并将输入文件解码为代表实际声音帧/样本的字节[] - 然后可用于 FFT 等。

    【讨论】:

    • 或者 .getAudioInputStream(URL) 如果 InputStream 引发了臭名昭著的标记/重置异常。
    【解决方案2】:

    将此文件写入ByteArrayOutputStream

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    BufferedInputStream in = new BufferedInputStream(new FileInputStream(WAV_FILE));
    
    int read;
    byte[] buff = new byte[1024];
    while ((read = in.read(buff)) > 0)
    {
        out.write(buff, 0, read);
    }
    out.flush();
    byte[] audioBytes = out.toByteArray();
    

    【讨论】:

    • 这是真的,因为 WAV 文件本质上是一个字节数组。并非所有的音频格式都是简单的字节流。例如,您无法对 MP3 文件执行此操作。
    • 好吧,wav 有片段和标题之类的散布在音频数据中,所以大卫在这个声明上得到了我的轻微技术分歧。也许更准确地指出 Java 支持的任何格式(或给定格式的体面库,包括 mp3)都会将给定文件转换为原始 PCM 数据的字节流。
    【解决方案3】:
    import java.io.*;
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    import java.util.LinkedHashMap;
    import javax.sound.sampled.*;
    
    /**
     * This class reads a .wav file and converts it to a bunch of byte arrays.
     * 
     * The info represented by these byte arrays is then printed out.
     * 
     * An example of playing these byte arrays with the speakers is used.
     * 
     * It also converts the byte arrays to a .wav file.
     * 
     * An extension of this concept can record from a microphone.
     * In this case, some values like sampling rate would need to be assumed.
     * 
     * See https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ for .wav file spec
     * 
     * @author sizu
     */
    public class WavFileHelper {    
    
        public static void main(String[] args) {
            final String NEWLINE = "\n";
            int recordingSampleRate = 22050;
            short recordingBitsPerSample = 16;
            short recordingNumChannels = 2;
            String inputFile = "/input.wav"; // Place the wav file in the top level directory, ie S:/input.wav
            String outputFile = "/output.wav";
            String recordedFile = "/capture.wav";
    
            System.out.println("START");
            try {
                WavData wavInputData = new WavData();
                WavData wavRecordData = new WavData();
                wavRecordData.put(WaveSection.SAMPLE_RATE, recordingSampleRate);
                wavRecordData.put(WaveSection.BITS_PER_SAMPLE, recordingBitsPerSample);
                wavRecordData.put(WaveSection.NUM_CHANNELS, recordingNumChannels);
    
                System.out.println(NEWLINE+"CONVERT WAV FILE TO BYTE ARRAY");
                wavInputData.read(inputFile);
    
                System.out.println(NEWLINE+"CONVERT BYTE ARRAY TO WAV FILE");
                wavInputData.write(outputFile);
    
                System.out.println(NEWLINE+"DISPLAY BYTE ARRAY INFORMATION FOR INPUT FILE");
                wavInputData.printByteInfo();
    
                System.out.println(NEWLINE+"START RECORDING - You can connect the microphone to the speakers");
                WavAudioRecorder recorder = new WavFileHelper.WavAudioRecorder(wavRecordData);
                recorder.startRecording();
    
                System.out.println(NEWLINE+"PLAY BYTE ARRAY (THIS WILL BE RECORDED)");
                WavAudioPlayer player = new WavFileHelper.WavAudioPlayer(wavInputData);
                player.playAudio();
    
                System.out.println(NEWLINE+"STOP RECORDING FOR RECORDING");
                recorder.stopRecording();
    
                System.out.println(NEWLINE+"DISPLAY BYTE ARRAY INFORMATION");
                wavRecordData.printByteInfo();
    
                System.out.println(NEWLINE+"SAVE RECORDING IN WAV FILE");
                wavRecordData.write(recordedFile);
    
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            System.out.println("FINISH");
        }
    
        public static enum WaveSection {
            // 12 Bytes
            CHUNK_ID(4, ByteOrder.BIG_ENDIAN),
            CHUNK_SIZE(4, ByteOrder.LITTLE_ENDIAN),
            FORMAT(4, ByteOrder.BIG_ENDIAN),
    
            // 24 Bytes
            SUBCHUNK1_ID(4, ByteOrder.BIG_ENDIAN),
            SUBCHUNK1_SIZE(4, ByteOrder.LITTLE_ENDIAN),
            AUDIO_FORMAT(2, ByteOrder.LITTLE_ENDIAN),
            NUM_CHANNELS(2, ByteOrder.LITTLE_ENDIAN),
            SAMPLE_RATE(4, ByteOrder.LITTLE_ENDIAN),
            BYTE_RATE(4, ByteOrder.LITTLE_ENDIAN),
            BLOCK_ALIGN(2, ByteOrder.LITTLE_ENDIAN),
            BITS_PER_SAMPLE(2, ByteOrder.LITTLE_ENDIAN),
    
            // 8 Bytes
            SUBCHUNK2_ID(4, ByteOrder.BIG_ENDIAN),
            SUBCHUNK2_SIZE(4, ByteOrder.LITTLE_ENDIAN),
            DATA(0, ByteOrder.LITTLE_ENDIAN),
            ;
    
            private Integer numBytes;
            private ByteOrder endian;
            WaveSection(Integer numBytes, ByteOrder endian){
                this.numBytes = numBytes;
                this.endian = endian;
            }
        }
    
        public static class WavData extends LinkedHashMap<WaveSection, byte[]>{
            static int HEADER_SIZE = 44; // There are 44 bits before the data section
            static int DEFAULT_SUBCHUNK1_SIZE = 16;
            static short DEFAULT_AUDIO_FORMAT = 1;
            static short DEFAULT_BLOCK_ALIGN = 4;
            static String DEFAULT_CHUNK_ID = "RIFF";
            static String DEFAULT_FORMAT = "WAVE";
            static String DEFAULT_SUBCHUNK1_ID = "fmt ";
            static String DEFAULT_SUBCHUNK2_ID = "data";
    
            public WavData(){
                this.put(WaveSection.CHUNK_ID, DEFAULT_CHUNK_ID);
                this.put(WaveSection.FORMAT, DEFAULT_FORMAT);
                this.put(WaveSection.SUBCHUNK1_ID, DEFAULT_SUBCHUNK1_ID);
                this.put(WaveSection.SUBCHUNK1_SIZE, DEFAULT_SUBCHUNK1_SIZE);
                this.put(WaveSection.AUDIO_FORMAT, DEFAULT_AUDIO_FORMAT);
                this.put(WaveSection.BLOCK_ALIGN, DEFAULT_BLOCK_ALIGN);
                this.put(WaveSection.SUBCHUNK2_ID, DEFAULT_SUBCHUNK2_ID);
    
                this.put(WaveSection.CHUNK_SIZE, 0);
                this.put(WaveSection.SUBCHUNK2_SIZE, 0);
                this.put(WaveSection.BYTE_RATE, 0);
            }
    
            public void put(WaveSection waveSection, String value){
                byte[] bytes = value.getBytes();
                this.put(waveSection, bytes);
            }
    
            public void put(WaveSection waveSection, int value) {
                byte[] bytes = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(value).array();
                this.put(waveSection, bytes);
            }
    
            public void put(WaveSection waveSection, short value) {
                byte[] bytes = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(value).array();
                this.put(waveSection, bytes);
            }
    
            public byte[] getBytes(WaveSection waveSection) {
                return this.get(waveSection);
            }
    
            public String getString(WaveSection waveSection) {
                byte[] bytes = this.get(waveSection);
                return new String(bytes);
            }
    
            public int getInt(WaveSection waveSection) {
                byte[] bytes = this.get(waveSection);
                return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
            }
    
            public short getShort(WaveSection waveSection) {
                byte[] bytes = this.get(waveSection);
                return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
            }
    
            public void printByteInfo() {
                for (WaveSection waveSection : WaveSection.values()) {
                    if (waveSection.numBytes == 4
                            && waveSection.endian == ByteOrder.BIG_ENDIAN) {
                        System.out.println("SECTION:" + waveSection + ":STRING:"
                                + this.getString(waveSection));
                    } else if (waveSection.numBytes == 4
                            && waveSection.endian == ByteOrder.LITTLE_ENDIAN) {
                        System.out.println("SECTION:" + waveSection + ":INTEGER:"
                                + this.getInt(waveSection));
                    } else if (waveSection.numBytes == 2
                            && waveSection.endian == ByteOrder.LITTLE_ENDIAN) {
                        System.out.println("SECTION:" + waveSection + ":SHORT:"
                                + this.getShort(waveSection));
                    } else {
                        // Data Section
                    }
                }
            }
    
            public void read(String inputPath) throws Exception {
                // Analyze redundant info
                int dataSize = (int) new File(inputPath).length() - HEADER_SIZE;
                WaveSection.DATA.numBytes  = dataSize; // Can't have two threads using this at the same time
    
                // Read from File
                DataInputStream inFile = new DataInputStream(new FileInputStream(inputPath));
    
                for (WaveSection waveSection : WaveSection.values()) {
                    byte[] readBytes = new byte[waveSection.numBytes];
                    for (int i = 0; i < waveSection.numBytes; i++) {
                        readBytes[i] = inFile.readByte();
                    }
                    this.put(waveSection, readBytes);
                }
    
                inFile.close();
            }
    
            public void write(String outputPath) throws Exception {
                // Analyze redundant info
                int dataSize = this.get(WaveSection.DATA).length;
                this.put(WaveSection.CHUNK_SIZE, dataSize+36);
                this.put(WaveSection.SUBCHUNK2_SIZE, dataSize);
    
                int byteRate = this.getInt(WaveSection.SAMPLE_RATE)*this.getShort(WaveSection.BLOCK_ALIGN);
                this.put(WaveSection.BYTE_RATE, byteRate);
    
                // Write to File
                DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(outputPath));
    
                for (WaveSection waveSection : WaveSection.values()) {
                    dataOutputStream.write(this.getBytes(waveSection));
                }
    
                dataOutputStream.close();
            }
    
            public AudioFormat createAudioFormat() {
                boolean audioSignedSamples = true; // Samples are signed
                boolean audioBigEndian = false;
                float sampleRate = (float) this.getInt(WaveSection.SAMPLE_RATE);
                int bitsPerSample = (int) this.getShort(WaveSection.BITS_PER_SAMPLE);
                int numChannels = (int) this.getShort(WaveSection.NUM_CHANNELS);
                return new AudioFormat(sampleRate, bitsPerSample,
                        numChannels, audioSignedSamples, audioBigEndian);
            }
        }
    
        public static class WavAudioPlayer {
            WavData waveData = new WavData();
    
            public WavAudioPlayer(WavData waveData){
                this.waveData = waveData;
            }
    
            public void playAudio() throws Exception {
                byte[] data = waveData.getBytes(WaveSection.DATA);
    
                // Create an audio input stream from byte array
                AudioFormat audioFormat = waveData.createAudioFormat();
                InputStream byteArrayInputStream = new ByteArrayInputStream(data);
                AudioInputStream audioInputStream = new AudioInputStream(byteArrayInputStream,
                        audioFormat, data.length / audioFormat.getFrameSize());
    
                // Write audio input stream to speaker source data line
                DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,
                        audioFormat);
                SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
                sourceDataLine.open(audioFormat);
                sourceDataLine.start();
    
                // Loop through input stream to write to source data line
                byte[] tempBuffer = new byte[10000];
                int cnt;
                while ((cnt = audioInputStream.read(tempBuffer, 0, tempBuffer.length)) != -1) {
                    sourceDataLine.write(tempBuffer, 0, cnt);
                }
    
                // Cleanup
                sourceDataLine.drain();
                sourceDataLine.close();
                byteArrayInputStream.close();
            }
        }
    
        public static class WavAudioRecorder implements Runnable {
            WavData waveData = new WavData();
            boolean recording = true;
            Thread runningThread;
            ByteArrayOutputStream byteArrayOutputStream;
    
            public WavAudioRecorder(WavData waveData){
                this.waveData = waveData;
            }
    
            public void startRecording(){
                this.recording = true;
                this.runningThread = new Thread(this);
                runningThread.start();  
            }
    
            public WavData stopRecording() throws Exception{
                this.recording = false;
                runningThread.stop();
    
                waveData.put(WaveSection.DATA, byteArrayOutputStream.toByteArray());
    
                return waveData;
            }
    
            public void run() {
                try {
                    // Create an audio output stream for byte array
                    byteArrayOutputStream  = new ByteArrayOutputStream();
    
                    // Write audio input stream to speaker source data line
                    AudioFormat audioFormat = waveData.createAudioFormat();
                    DataLine.Info info = new DataLine.Info(TargetDataLine.class, audioFormat);
                    TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
                    targetDataLine.open(audioFormat);
                    targetDataLine.start();
    
                    // Loop through target data line to write to output stream
                    int numBytesRead;
                    byte[] data = new byte[targetDataLine.getBufferSize() / 5];
                    while(recording) {
                        numBytesRead =  targetDataLine.read(data, 0, data.length);
                        byteArrayOutputStream.write(data, 0, numBytesRead);
                    }
    
                    // Cleanup
                    targetDataLine.stop();
                    targetDataLine.close();
                    byteArrayOutputStream.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      将文件转换为字节数组

      fileToByteArray("C:\..\my.mp3");

      `public static byte[] fileToByteArray(String name){
          Path path = Paths.get(name);
          try {
              return Files.readAllBytes(path);
          } catch (IOException e) {
              e.printStackTrace();
              return null;
          }
      }`
      

      【讨论】:

        猜你喜欢
        • 2011-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-19
        • 1970-01-01
        • 2014-02-19
        • 2012-09-05
        • 2012-12-09
        相关资源
        最近更新 更多