简体   繁体   English

如何使用 Java 中的 ByteArrayOutputStream 编写 WAV 文件

[英]How to write WAV files using ByteArrayOutputStream in Java

I'm trying to make a system that starts listening everything on a mic without recording, that stores it in a ByteArrayOutputStream object and when it reaches a certain level it starts recording, when it drops below the selected level that stops recording again but keeps listening and so on...我正在尝试制作一个系统,该系统可以在不录制的情况下开始收听麦克风上的所有内容,并将其存储在 ByteArrayOutputStream object 中,当它达到某个级别时,它开始录制,当它低于所选级别时,它会再次停止录制但继续收听等等...

This is the code I am using:这是我正在使用的代码:

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;

public class tests {

    protected static boolean running;
    private static ByteArrayOutputStream output;
    final static float MAX_16_BITS_SIGNED = Short.MAX_VALUE;
    final static float MAX_16_BITS_UNSIGNED = 0xffff;
    private static float level;

    private static AudioFormat getFormat() {
        return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100.0F, 16, 2, 4, 44100.0F, false);
    }

    private static void stopAudio() {
        OutputStream wavOutput = null;
        try {
            System.out.println("Saving...");
            rinning = false;
            wavOutput = new FileOutputStream(System.getProperty("user.home") + "/Desktop/test1.wav");
            output.writeTo(wavOutput);
            System.out.println("WAV file saved. Goodbye!");
        } catch (FileNotFoundException ex) {
            Logger.getLogger(tests.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(tests.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                wavOutput.close();
            } catch (IOException ex) {
                Logger.getLogger(tests.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private static void recordingAudio() {
        try {
            final AudioFormat format = getFormat();
            DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
            final TargetDataLine mic = (TargetDataLine) AudioSystem.getLine(info);
            mic.open(format);
            mic.start();
            Thread tRecording = new Thread(new Runnable() {
                int bufferLength = (int) format.getSampleRate() * format.getFrameSize();
                byte buffer[] = new byte[bufferLength];

                public void run() {
                    output = new ByteArrayOutputStream();
                    running = true;
                    while (running) {
                        int count = mic.read(buffer, 0, buffer.length);
                        calculateLevel(buffer, 0, 0);
                        int levelPercent = (int) (level * 100);
                        int gain = 50;
                        if (levelPercent > gain) {
                            output.write(buffer, 0, count);
                            System.out.println("Recording");
                        }
                    }
                    mic.stop();
                }
            });
            tRecording.start();
        } catch (LineUnavailableException e) {
            System.err.println("Line unavailable: " + e);
            System.exit(-2);
        }
    }

    private static void calculateLevel(byte[] buffer, int readPoint, int leftOver) {
        int max = 0;
        boolean signed = (getFormat().getEncoding() == AudioFormat.Encoding.PCM_SIGNED);
        boolean bigEndian = (getFormat().isBigEndian());
        for (int i = readPoint; i < buffer.length - leftOver; i += 2) {
            int value = 0;
            int hiByte = (bigEndian ? buffer[i] : buffer[i + 1]);
            int loByte = (bigEndian ? buffer[i + 1] : buffer[i]);
            if (signed) {
                short shortVal = (short) hiByte;
                shortVal = (short) ((shortVal << 8) | (byte) loByte);
                value = shortVal;
            } else {
                value = (hiByte << 8) | loByte;
            }
            max = Math.max(max, value);
        }
        if (signed) {
            level = (float) max / MAX_16_BITS_SIGNED;
        } else {
            level = (float) max / MAX_16_BITS_UNSIGNED;
        }
    }

    public static void main(String args[]) {
        recordingAudio();
        System.out.println("Stop recording press '1' + Enter");
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        try {
            if (br.readLine().equals("1")) {
                stopAudio();
            }
        } catch (IOException ex) {
            Logger.getLogger(pruebas.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

I can detect audio level, just need to save it... In the stopAudio() method is where ByteArrayOutputStream should be converted to WAV file, and it works, but I can't plaly it我可以检测音频电平,只需要保存它...在 stopAudio() 方法中应该将 ByteArrayOutputStream 转换为 WAV 文件,它可以工作,但我不能播放它

It's not a WAV format file you're saving, it's the raw audio data.您保存的不是 WAV 格式文件,而是原始音频数据。 You'd need to write that data as a WAV file.需要将该数据写入 WAV 文件。

Although this question is a bit outdated, there are some references and libraries that might still be usable (or just find a more recent library from somewhere).虽然这个问题有点过时,但有一些参考资料和库可能仍然可用(或者只是从某个地方找到更新的库)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM