如何在java中计算音频信号的分贝并录制音频? 如何同时计算音频的分贝 如何计算现有wav文件的分贝

如何在java中计算音频信号的分贝并录制音频? 如何同时计算音频的分贝 如何计算现有wav文件的分贝,java,audio,wav,decibel,audioformat,Java,Audio,Wav,Decibel,Audioformat,假设一:您希望在录制结束时处理并保存数据 使用将数据读入临时短缓冲区 使用将数据写入由TearrayOutputStream生成的中 将ByteArrayOutputStream转换为字节[]数组 将字节数据编码到样本中 计算RMS、峰值等,并将其转换为分贝 使用byte[]数组构造ByteArrayInputStream 使用AudioSystem.write() 假设二:您希望连续读取、处理和保存数据 您需要一个中间类才能将ByteArrayOutputStream转换为ByteArr

假设一:您希望在录制结束时处理并保存数据

  • 使用将数据读入临时短缓冲区
  • 使用将数据写入由TearrayOutputStream生成的
  • ByteArrayOutputStream
    转换为
    字节[]
    数组
  • 将字节数据编码到样本中
  • 计算RMS、峰值等,并将其转换为分贝
  • 使用
    byte[]
    数组构造
    ByteArrayInputStream
  • 使用
    AudioSystem.write()

假设二:您希望连续读取、处理和保存数据

您需要一个中间类才能将
ByteArrayOutputStream
转换为
ByteArrayInputStream
。在后台线程中捕获音频数据,在另一个线程中处理并保存所需数据量可用时的数据

编码:您可以对
字节[]
数组中的音频样本进行编码。在您的示例中,两个连续的字节生成一个示例。您将一个接一个地获取两个通道的样本。如果您有任何特定于通道的处理,则需要分离每个通道的样本。以下代码段可能有助于您进行编码-

int numBytesRead = 0;
byte[] buffer = new byte[1024]; 
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
boolean stopRecording = false;

while (!stopRecording) {
    numBytesRead =  targetDataLine.read(buffer, 0, buffer.length);
    //short[] samples = encodeToSample(buffer, buffer.length);
    // process samples - calculate decibels

    if (numBytesRead > 0) {
        outStream.write(buffer, 0, numBytesRead);
    }
}

outStream.close();

byte[] data = outStream.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(data);
AudioInputStream ais = new AudioInputStream(bais, a, data.length);

AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("record.wav"));

假设一:您希望在录制结束时处理并保存数据

  • 使用将数据读入临时短缓冲区
  • 使用将数据写入由TearrayOutputStream生成的
  • ByteArrayOutputStream
    转换为
    字节[]
    数组
  • 将字节数据编码到样本中
  • 计算RMS、峰值等,并将其转换为分贝
  • 使用
    byte[]
    数组构造
    ByteArrayInputStream
  • 使用
    AudioSystem.write()

假设二:您希望连续读取、处理和保存数据

您需要一个中间类才能将
ByteArrayOutputStream
转换为
ByteArrayInputStream
。在后台线程中捕获音频数据,在另一个线程中处理并保存所需数据量可用时的数据

编码:您可以对
字节[]
数组中的音频样本进行编码。在您的示例中,两个连续的字节生成一个示例。您将一个接一个地获取两个通道的样本。如果您有任何特定于通道的处理,则需要分离每个通道的样本。以下代码段可能有助于您进行编码-

int numBytesRead = 0;
byte[] buffer = new byte[1024]; 
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
boolean stopRecording = false;

while (!stopRecording) {
    numBytesRead =  targetDataLine.read(buffer, 0, buffer.length);
    //short[] samples = encodeToSample(buffer, buffer.length);
    // process samples - calculate decibels

    if (numBytesRead > 0) {
        outStream.write(buffer, 0, numBytesRead);
    }
}

outStream.close();

byte[] data = outStream.toByteArray();
ByteArrayInputStream bais = new ByteArrayInputStream(data);
AudioInputStream ais = new AudioInputStream(bais, a, data.length);

AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("record.wav"));

这个数字代表32768,你的样本量是16位。因此,样本的存储范围为-32768到+32767。通过除以数字32768(最大可能值),我们将从-1到+1的范围归一化。@IhabKhaledShhadat这个答案有用吗?这个数字代表的是32768您的位样本量是16。因此,样本的存储范围为-32768到+32767。通过除以数字32768(最大可能值),我们将从-1到+1的范围归一化。@IhabKhaledShhadat这个答案有用吗?
public static short[] encodeToSample(byte[] srcBuffer, int numBytes) {
    byte[] tempBuffer = new byte[2];
    int nSamples = numBytes / 2;        
    short[] samples = new short[nSamples];  // 16-bit signed value

    for (int i = 0; i < nSamples; i++) {
        tempBuffer[0] = srcBuffer[2 * i];
        tempBuffer[1] = srcBuffer[2 * i + 1];
        samples[i] = bytesToShort(tempBuffer);
    }

    return samples;
}

public static short bytesToShort(byte [] buffer) {
    ByteBuffer bb = ByteBuffer.allocate(2);
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.put(buffer[0]);
    bb.put(buffer[1]);
    return bb.getShort(0);
}
public static void calculatePeakAndRms(short [] samples) {
    double sumOfSampleSq = 0.0;    // sum of square of normalized samples.
    double peakSample = 0.0;     // peak sample.

    for (short sample : samples) {
        double normSample = (double) sample / 32767;  // normalized the sample with maximum value.
        sumOfSampleSq += (normSample * normSample);
        if (Math.abs(sample) > peakSample) {
            peakSample = Math.abs(sample);
        }
    }

    double rms = 10*Math.log10(sumOfSampleSq / samples.length);
    double peak = 20*Math.log10(peakSample / 32767);
}