How to calculate the decibel of audio signal and r

2019-08-17 05:57发布

public TargetDataLine targetDataLine;
private static AudioFormat getAudioFormat() 
{
        return new AudioFormat(16000, 16, 2, true, false);
}
AudioFormat a = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, a);
targetDataLine = (TargetDataLine) AudioSystem.getLine(info);
targetDataLine.open(a);
targetDataLine.start();
AudioInputStream ais = new AudioInputStream(targetDataLine); 
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, new File("record.wav"));
  1. How can i calculate the decibel of audio at the same time?
  2. How can i calculate the decibel of existing wav file?

1条回答
不美不萌又怎样
2楼-- · 2019-08-17 06:25

Assumption One: You would like to process and save the data at the end of your recording.

  • Read data into a temporary short buffer using TargetDataLine.read()
  • Write data into a ByteArrayOutputStream using ByteArrayOutputStream.write()
  • Convert the ByteArrayOutputStream into byte[] array.
  • Encode byte data into samples
  • Calculate RMS, Peak, etc. and convert them into decibels.
  • Construct ByteArrayInputStream using your byte[] array
  • Produce your audio file using AudioSystem.write()

    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"));
    

Assumption Two: You would like to read, process, and save the data continuously.

You need an intermediate class in order to convert ByteArrayOutputStream to ByteArrayInputStream. In a background thread capture audio data, and in another thread process and save the data when your desired amount of data is available.

Encoding: You can encode audio samples from your byte[] array. In your case, two consecutive bytes produce one sample. You will get the samples for both channels one after another. If you have any channel specific processing then you need to segregate the samples for each channel. The following code snippet may help you for encoding -

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);
}

Decibel: Db is a logarithmic ratio of a given level with a reference level. For example, if you would like to calculate RMS/Peak in dBFS, following code snippet may help you.

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);
}
查看更多
登录 后发表回答