录音时检测静音

发布于 2024-11-03 20:36:59 字数 5430 浏览 3 评论 0原文

在Java中,如何在开始录制操作时检测静音?什么是PCM数据?如何用Java计算PCM数据?

我找到了解决方案:

package bemukan.voiceRecognition.speechToText;

import javax.sound.sampled.*;
import java.io.*;

public class RecordAudio {
    private File audioFile;
    protected boolean running;
    private ByteArrayOutputStream out;
    private AudioInputStream inputStream;
    final static float MAX_8_BITS_SIGNED = Byte.MAX_VALUE;
    final static float MAX_8_BITS_UNSIGNED = 0xff;
    final static float MAX_16_BITS_SIGNED = Short.MAX_VALUE;
    final static float MAX_16_BITS_UNSIGNED = 0xffff;
    private AudioFormat format;
    private float level;
    private int frameSize;

    public RecordAudio(){
         getFormat();
    }

    private AudioFormat getFormat() {
        File file = new File("src/Facebook/1.wav");
        AudioInputStream stream;
        try {
            stream = AudioSystem.getAudioInputStream(file);
            format=stream.getFormat();
            frameSize=stream.getFormat().getFrameSize();
            return stream.getFormat();
        } catch (UnsupportedAudioFileException e) {

        } catch (IOException e) {

        }
        return null;
    }

    public void stopAudio() {

        running = false;
    }

    public void recordAudio() {

        try {
            final AudioFormat format = getFormat();
            DataLine.Info info = new DataLine.Info(
                    TargetDataLine.class, format);
            final TargetDataLine line = (TargetDataLine)
                    AudioSystem.getLine(info);
            line.open(format);
            line.start();
            Runnable runner = new Runnable() {
                int bufferSize = (int) format.getSampleRate()
                        * format.getFrameSize();
                byte buffer[] = new byte[bufferSize];

                public void run() {
                     int readPoint = 0;

                    out = new ByteArrayOutputStream();
                    running = true;
                     int sum=0;
                    while (running) {
                        int count =
                              line.read(buffer, 0, buffer.length);
                              calculateLevel(buffer,0,0);
                         System.out.println(level);

                        if (count > 0) {
                            out.write(buffer, 0, count);
                        }
                    }
                    line.stop();
                }
            };
            Thread captureThread = new Thread(runner);
            captureThread.start();
        } catch (LineUnavailableException e) {
            System.err.println("Line unavailable: " + e);
            System.exit(-2);
        }
    }

    public File getAudioFile() {
        byte[] audio = out.toByteArray();
        InputStream input = new ByteArrayInputStream(audio);
        try {

            final AudioFormat format = getFormat();
            final AudioInputStream ais =
                    new AudioInputStream(input, format,
                            audio.length / format.getFrameSize());
            AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("temp.wav"));
            input.close();
            System.out.println("New file created!");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        return new File("temp.wav");
    }
    private void calculateLevel (byte[] buffer,
                                 int readPoint,
                                 int leftOver) {
        int max = 0;
        boolean use16Bit = (format.getSampleSizeInBits() == 16);
        boolean signed = (format.getEncoding() ==
                          AudioFormat.Encoding.PCM_SIGNED);
        boolean bigEndian = (format.isBigEndian());
        if (use16Bit) {
            for (int i=readPoint; i<buffer.length-leftOver; i+=2) {
                int value = 0;
                // deal with endianness
                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);
            } // for
        } else {
            // 8 bit - no endianness issues, just sign
            for (int i=readPoint; i<buffer.length-leftOver; i++) {
                int value = 0;
                if (signed) {
                    value = buffer [i];
                } else {
                    short shortVal = 0;
                    shortVal = (short) (shortVal | buffer [i]);
                    value = shortVal;
                }
                max = Math.max (max, value);
            } // for
        } // 8 bit
        // express max as float of 0.0 to 1.0 of max value
        // of 8 or 16 bits (signed or unsigned)
        if (signed) {
            if (use16Bit) { level = (float) max / MAX_16_BITS_SIGNED; }
            else { level = (float) max / MAX_8_BITS_SIGNED; }
        } else {
            if (use16Bit) { level = (float) max / MAX_16_BITS_UNSIGNED; }
            else { level = (float) max / MAX_8_BITS_UNSIGNED; }
        }
    } // calculateLevel


}

How can I detect silence when recording operation is started in Java? What is PCM data? How can I calculate PCM data in Java?

I found the solution :

package bemukan.voiceRecognition.speechToText;

import javax.sound.sampled.*;
import java.io.*;

public class RecordAudio {
    private File audioFile;
    protected boolean running;
    private ByteArrayOutputStream out;
    private AudioInputStream inputStream;
    final static float MAX_8_BITS_SIGNED = Byte.MAX_VALUE;
    final static float MAX_8_BITS_UNSIGNED = 0xff;
    final static float MAX_16_BITS_SIGNED = Short.MAX_VALUE;
    final static float MAX_16_BITS_UNSIGNED = 0xffff;
    private AudioFormat format;
    private float level;
    private int frameSize;

    public RecordAudio(){
         getFormat();
    }

    private AudioFormat getFormat() {
        File file = new File("src/Facebook/1.wav");
        AudioInputStream stream;
        try {
            stream = AudioSystem.getAudioInputStream(file);
            format=stream.getFormat();
            frameSize=stream.getFormat().getFrameSize();
            return stream.getFormat();
        } catch (UnsupportedAudioFileException e) {

        } catch (IOException e) {

        }
        return null;
    }

    public void stopAudio() {

        running = false;
    }

    public void recordAudio() {

        try {
            final AudioFormat format = getFormat();
            DataLine.Info info = new DataLine.Info(
                    TargetDataLine.class, format);
            final TargetDataLine line = (TargetDataLine)
                    AudioSystem.getLine(info);
            line.open(format);
            line.start();
            Runnable runner = new Runnable() {
                int bufferSize = (int) format.getSampleRate()
                        * format.getFrameSize();
                byte buffer[] = new byte[bufferSize];

                public void run() {
                     int readPoint = 0;

                    out = new ByteArrayOutputStream();
                    running = true;
                     int sum=0;
                    while (running) {
                        int count =
                              line.read(buffer, 0, buffer.length);
                              calculateLevel(buffer,0,0);
                         System.out.println(level);

                        if (count > 0) {
                            out.write(buffer, 0, count);
                        }
                    }
                    line.stop();
                }
            };
            Thread captureThread = new Thread(runner);
            captureThread.start();
        } catch (LineUnavailableException e) {
            System.err.println("Line unavailable: " + e);
            System.exit(-2);
        }
    }

    public File getAudioFile() {
        byte[] audio = out.toByteArray();
        InputStream input = new ByteArrayInputStream(audio);
        try {

            final AudioFormat format = getFormat();
            final AudioInputStream ais =
                    new AudioInputStream(input, format,
                            audio.length / format.getFrameSize());
            AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("temp.wav"));
            input.close();
            System.out.println("New file created!");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        return new File("temp.wav");
    }
    private void calculateLevel (byte[] buffer,
                                 int readPoint,
                                 int leftOver) {
        int max = 0;
        boolean use16Bit = (format.getSampleSizeInBits() == 16);
        boolean signed = (format.getEncoding() ==
                          AudioFormat.Encoding.PCM_SIGNED);
        boolean bigEndian = (format.isBigEndian());
        if (use16Bit) {
            for (int i=readPoint; i<buffer.length-leftOver; i+=2) {
                int value = 0;
                // deal with endianness
                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);
            } // for
        } else {
            // 8 bit - no endianness issues, just sign
            for (int i=readPoint; i<buffer.length-leftOver; i++) {
                int value = 0;
                if (signed) {
                    value = buffer [i];
                } else {
                    short shortVal = 0;
                    shortVal = (short) (shortVal | buffer [i]);
                    value = shortVal;
                }
                max = Math.max (max, value);
            } // for
        } // 8 bit
        // express max as float of 0.0 to 1.0 of max value
        // of 8 or 16 bits (signed or unsigned)
        if (signed) {
            if (use16Bit) { level = (float) max / MAX_16_BITS_SIGNED; }
            else { level = (float) max / MAX_8_BITS_SIGNED; }
        } else {
            if (use16Bit) { level = (float) max / MAX_16_BITS_UNSIGNED; }
            else { level = (float) max / MAX_8_BITS_UNSIGNED; }
        }
    } // calculateLevel


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谎言 2024-11-10 20:36:59

如何在 Java 中检测开始录音操作时的静音?

计算 dBRMS 一组声音帧的值,并决定在什么级别将其视为“静音”。

什么是 PCM 数据?

采用脉冲编码调制格式的数据。

如何用Java计算PCM数据?

我不明白这个问题。但猜测它与speech-recognition标签有关,我有一些坏消息。理论上,这可以使用 Java Speech API 来完成。但显然该 API 没有可用的“语音转文本”实现(只有“文本转语音”)。


我必须计算语音识别项目的均方根。但我不知道如何用Java计算。

对于由 -1 到 1 范围内的 double 信号大小表示的单个通道,您可以使用此方法。

/** Computes the RMS volume of a group of signal sizes ranging from -1 to 1. */
public double volumeRMS(double[] raw) {
    double sum = 0d;
    if (raw.length==0) {
        return sum;
    } else {
        for (int ii=0; ii<raw.length; ii++) {
            sum += raw[ii];
        }
    }
    double average = sum/raw.length;

    double sumMeanSquare = 0d;
    for (int ii=0; ii<raw.length; ii++) {
        sumMeanSquare += Math.pow(raw[ii]-average,2d);
    }
    double averageMeanSquare = sumMeanSquare/raw.length;
    double rootMeanSquare = Math.sqrt(averageMeanSquare);

    return rootMeanSquare;
}

有一个字节缓冲区来保存行中的输入值,我应该如何处理该缓冲区?

如果使用 volumeRMS(double[]) 方法,请将 byte 值转换为范围从 -1 到 1 的 double 值数组。 )

How can I detect silence when recording operation is started in Java?

Calculate the dB or RMS value for a group of sound frames and decide at what level it is considered to be 'silence'.

What is PCM data?

Data that is in Pulse-code modulation format.

How can I calculate PCM data in Java?

I do not understand that question. But guessing it has something to do with the speech-recognition tag, I have some bad news. This might theoretically be done using the Java Speech API. But there are apparently no 'speech to text' implementations available for the API (only 'text to speech').


I have to calculate rms for speech-recognition project. But I do not know how can I calculate in Java.

For a single channel that is represented by signal sizes in a double ranging from -1 to 1, you might use this method.

/** Computes the RMS volume of a group of signal sizes ranging from -1 to 1. */
public double volumeRMS(double[] raw) {
    double sum = 0d;
    if (raw.length==0) {
        return sum;
    } else {
        for (int ii=0; ii<raw.length; ii++) {
            sum += raw[ii];
        }
    }
    double average = sum/raw.length;

    double sumMeanSquare = 0d;
    for (int ii=0; ii<raw.length; ii++) {
        sumMeanSquare += Math.pow(raw[ii]-average,2d);
    }
    double averageMeanSquare = sumMeanSquare/raw.length;
    double rootMeanSquare = Math.sqrt(averageMeanSquare);

    return rootMeanSquare;
}

There is a byte buffer to save input values from the line, and what I should have to do with this buffer?

If using the volumeRMS(double[]) method, convert the byte values to an array of double values ranging from -1 to 1. ;)

破晓 2024-11-10 20:36:59

您需要捕获该值,例如数字静音为零或接近零

请根据您的要求调整您的代码!
在本例中,名为 UMBRAL(西班牙语中的阈值)的变量...

假设您可以访问 WAV 文件,例如字节 ByteHeader...

private Integer Byte2PosIntBig(byte Byte24, byte Byte16, byte Byte08, byte Byte00) {
    return new Integer (
            ((Byte24) << 24)|
            ((Byte16 & 0xFF) << 16)|
            ((Byte08 & 0xFF) << 8)|
            ((Byte00 & 0xFF) << 0));
} 

之前 ....

    RandomAccessFile RAFSource = new RandomAccessFile("your old file wav", "r");

从这里开始...

int PSData = 44;
byte[] Bytes = new byte[4];
byte[] ByteHeader = new byte[44];
RAFSource.seek(0);
RAFSource.read(ByteHeader);

int WavSize = Byte2PosIntBig(ByteHeader[43],ByteHeader[42],ByteHeader[41],ByteHeader[40]);

int NumBits = Byte2PosIntBig(ByteHeader[35],ByteHeader[34]);
int NumByte = NumBits/8;

    for (int i = PSData;i < PSData+WavSize;i+=NumByte) {
      int WavSample = 0;
      int WavResultI =0;
      int WavResultO = 0;
      if (NumByte == 2) {

          RAFSource.seek(i);
          Bytes[0] = RAFSource.readByte();
          Bytes[1] = RAFSource.readByte();
          WavSample = (int)(((Bytes[1]) << 8)|((Bytes[0] & 0xFF) << 0));
          if (Math.abs(WavSample) < UMBRAL) {
            //SILENCE DETECTED!!!
          }

      } else {
        RAFSource.seek(i);
        WavSample = (short)(RAFSource.readByte() & 0xFF);
        short sSamT = (short)WavSample;
        sSamT += 128;
        double dSamD = (double)sSamT*Multiplier;
        if ((double)sSamT < UMBRAL) {
          //SILENCE DETECTED!!!
        }
      }

You need to catch the value like a number silence is zero or near

Please adapt your code to your requirement!!!
In this case a variable named UMBRAL (Threshold in spanish)...

Suppose that you have access to WAV file like bytes ByteHeader...

private Integer Byte2PosIntBig(byte Byte24, byte Byte16, byte Byte08, byte Byte00) {
    return new Integer (
            ((Byte24) << 24)|
            ((Byte16 & 0xFF) << 16)|
            ((Byte08 & 0xFF) << 8)|
            ((Byte00 & 0xFF) << 0));
} 

Before ....

    RandomAccessFile RAFSource = new RandomAccessFile("your old file wav", "r");

Begins here...

int PSData = 44;
byte[] Bytes = new byte[4];
byte[] ByteHeader = new byte[44];
RAFSource.seek(0);
RAFSource.read(ByteHeader);

int WavSize = Byte2PosIntBig(ByteHeader[43],ByteHeader[42],ByteHeader[41],ByteHeader[40]);

int NumBits = Byte2PosIntBig(ByteHeader[35],ByteHeader[34]);
int NumByte = NumBits/8;

    for (int i = PSData;i < PSData+WavSize;i+=NumByte) {
      int WavSample = 0;
      int WavResultI =0;
      int WavResultO = 0;
      if (NumByte == 2) {

          RAFSource.seek(i);
          Bytes[0] = RAFSource.readByte();
          Bytes[1] = RAFSource.readByte();
          WavSample = (int)(((Bytes[1]) << 8)|((Bytes[0] & 0xFF) << 0));
          if (Math.abs(WavSample) < UMBRAL) {
            //SILENCE DETECTED!!!
          }

      } else {
        RAFSource.seek(i);
        WavSample = (short)(RAFSource.readByte() & 0xFF);
        short sSamT = (short)WavSample;
        sSamT += 128;
        double dSamD = (double)sSamT*Multiplier;
        if ((double)sSamT < UMBRAL) {
          //SILENCE DETECTED!!!
        }
      }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文