java音乐计算电平,如何计算java中音频信号的电平/幅度/ db?

主要问题似乎是您正在错误地读取音频数据.

具体来说,我不确定这段摘录应该是什么意思:

if (tempBuffer[j] > tempBuffer[j+1])

... tempBuffer[j] - tempBuffer[j+1];

else

... tempBuffer[j + 1] - tempBuffer[j];

但无论如何,由于您正在记录16位数据,因此字节数组中的字节本身没有意义.每个字节仅代表每个样本中的1/2位.在你可以对它们做任何事情之前,你需要将它们“解包”到int,float等等.对于原始LPCM,连接字节是通过移位它们并将它们“或”在一起来完成的.

这是一个MCVE,用于演示Java中的基本电平表(RMS和简单峰值保持).

import javax.swing.SwingUtilities;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JComponent;

import java.awt.BorderLayout;

import java.awt.Graphics;

import java.awt.Color;

import java.awt.Dimension;

import javax.swing.border.EmptyBorder;

import javax.sound.sampled.AudioFormat;

import javax.sound.sampled.TargetDataLine;

import javax.sound.sampled.AudioSystem;

import javax.sound.sampled.LineUnavailableException;

public class LevelMeter extends JComponent {

private int meterWidth = 10;

private float amp = 0f;

private float peak = 0f;

public void setAmplitude(float amp) {

this.amp = Math.abs(amp);

repaint();

}

public void setPeak(float peak) {

this.peak = Math.abs(peak);

repaint();

}

public void setMeterWidth(int meterWidth) {

this.meterWidth = meterWidth;

}

@Override

protected void paintComponent(Graphics g) {

int w = Math.min(meterWidth, getWidth());

int h = getHeight();

int x = getWidth() / 2 - w / 2;

int y = 0;

g.setColor(Color.LIGHT_GRAY);

g.fillRect(x, y, w, h);

g.setColor(Color.BLACK);

g.drawRect(x, y, w - 1, h - 1);

int a = Math.round(amp * (h - 2));

g.setColor(Color.GREEN);

g.fillRect(x + 1, y + h - 1 - a, w - 2, a);

int p = Math.round(peak * (h - 2));

g.setColor(Color.RED);

g.drawLine(x + 1, y + h - 1 - p, x + w - 1, y + h - 1 - p);

}

@Override

public Dimension getMinimumSize() {

Dimension min = super.getMinimumSize();

if(min.width < meterWidth)

min.width = meterWidth;

if(min.height < meterWidth)

min.height = meterWidth;

return min;

}

@Override

public Dimension getPreferredSize() {

Dimension pref = super.getPreferredSize();

pref.width = meterWidth;

return pref;

}

@Override

public void setPreferredSize(Dimension pref) {

super.setPreferredSize(pref);

setMeterWidth(pref.width);

}

public static void main(String[] args) {

SwingUtilities.invokeLater(new Runnable() {

@Override

public void run() {

JFrame frame = new JFrame("Meter");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel content = new JPanel(new BorderLayout());

content.setBorder(new EmptyBorder(25, 50, 25, 50));

LevelMeter meter = new LevelMeter();

meter.setPreferredSize(new Dimension(9, 100));

content.add(meter, BorderLayout.CENTER);

frame.setContentPane(content);

frame.pack();

frame.setLocationRelativeTo(null);

frame.setVisible(true);

new Thread(new Recorder(meter)).start();

}

});

}

static class Recorder implements Runnable {

final LevelMeter meter;

Recorder(final LevelMeter meter) {

this.meter = meter;

}

@Override

public void run() {

AudioFormat fmt = new AudioFormat(44100f, 16, 1, true, false);

final int bufferByteSize = 2048;

TargetDataLine line;

try {

line = AudioSystem.getTargetDataLine(fmt);

line.open(fmt, bufferByteSize);

} catch(LineUnavailableException e) {

System.err.println(e);

return;

}

byte[] buf = new byte[bufferByteSize];

float[] samples = new float[bufferByteSize / 2];

float lastPeak = 0f;

line.start();

for(int b; (b = line.read(buf, 0, buf.length)) > -1;) {

// convert bytes to samples here

for(int i = 0, s = 0; i < b;) {

int sample = 0;

sample |= buf[i++] & 0xFF; // (reverse these two lines

sample |= buf[i++] << 8; // if the format is big endian)

// normalize to range of +/-1.0f

samples[s++] = sample / 32768f;

}

float rms = 0f;

float peak = 0f;

for(float sample : samples) {

float abs = Math.abs(sample);

if(abs > peak) {

peak = abs;

}

rms += sample * sample;

}

rms = (float)Math.sqrt(rms / samples.length);

if(lastPeak > peak) {

peak = lastPeak * 0.875f;

}

lastPeak = peak;

setMeterOnEDT(rms, peak);

}

}

void setMeterOnEDT(final float rms, final float peak) {

SwingUtilities.invokeLater(new Runnable() {

@Override

public void run() {

meter.setAmplitude(rms);

meter.setPeak(peak);

}

});

}

}

}

请注意,格式转换在那里是硬编码的.

有关:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值