How to calculate the decibel of audio signal and record the audio in java?

跟風遠走 提交于 2019-12-24 21:43:42

问题


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:


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


来源:https://stackoverflow.com/questions/49097889/how-to-calculate-the-decibel-of-audio-signal-and-record-the-audio-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!