- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想在 java 中为麦克风创建一个音频电平表来检查输入的音量。它应该看起来像操作系统之一。我不是在问 gui。它只是计算
产生的字节流中的音频电平n = targetDataLine.read( tempBuffer , 0 , tempBuffer.length );
所以我已经有一些正在运行的东西,但它甚至离我的操作系统 (windows) 的电平表还差得很远,它卡在中间。我的值介于 0 和 100 之间,这很好,但在中间音量中,无论输入有多大声,它都会停留在 60 左右。
我现在是这样计算的:
amplitude = 0;
for (int j = 0; j < tempBuffer.length; j = j +2 ){
if (tempBuffer[j] > tempBuffer[j+1])
amplitude = amplitude + tempBuffer[j] - tempBuffer[j+1];
else amplitude = amplitude + tempBuffer[j + 1] - tempBuffer[j];
}
amplitude = amplitude / tempBuffer.length * 2;
是否有更好/更精确的方法来计算音频电平以进行监控?还是我可能犯了一个重大错误?
这是我的音频格式:
public static AudioFormat getAudioFormat(){
float sampleRate = 20000.0F;
//8000,11025,16000,22050,44100
int sampleSizeInBits = 16;
//8,16
int channels = 1;
//1,2
boolean signed = true;
//true,false
boolean bigEndian = false;
//true,false
return new AudioFormat( sampleRate, sampleSizeInBits, channels, signed, bigEndian );
//return new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000.0F, 8, 1, 1, 8000.0F, false);
}
最佳答案
主要问题似乎是您读取的音频数据不正确。
具体来说,我不太确定这段摘录是什么意思:
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);
}
});
}
}
}
注意格式转换是硬编码的。
您还可以看到 "How do I use audio sample data from Java Sound?"我详细解释了如何从原始字节中解压音频数据。
相关:
关于java - 如何计算java中音频信号的电平/幅度/分贝?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26574326/
所以,我有一个 Triangle->AABB 碰撞算法,我让它返回 AABB 碰撞的三角形。我希望三角形的 3 个 vector 和运动的方向/幅度能让我确定一个偏转 vector ,这样当你以一个角
我希望我能找到一种方法从 python 中的 mp3 中获取振幅数据。与 audacity 类似,但我不想要视觉效果,一个简单的值数组就可以了。当声音变大时,我希望我的代码在某些时候对声音使用reac
在 OpenCV 中,如何计算 Mat 中的平均梯度强度和平均梯度方向? 我已经通过谷歌搜索找到了以下方法,但我想在继续下一步之前确认我确实在正确地执行此操作。 这是正确的吗? Mat img = i
我想在 java 中为麦克风创建一个音频电平表来检查输入的音量。它应该看起来像操作系统之一。我不是在问 gui。它只是计算 产生的字节流中的音频电平 n = targetDataLine.read(
我正在开发一个应用程序,该应用程序既可以录制音频文件,也可以选择在录制完成后播放该文件。 UI 有一个 EQ 组件,该组件相对于当前录音幅度进行动画处理。我已经通过 MediaRecorder.get
我读过两篇关于从 AudioInputStream 中提取样本并将其转换为 dB 的文章。 https://stackoverflow.com/a/26576548/8428414 https://s
我的目标是在 OpenCV 中获取图像的DFT。 使用 dft 函数,我能够计算它,然后通过计算它的大小来绘制它(然后,应用对数并最终对其进行归一化,以便绘制介于 0 和 1 之间的值) . 我的结果
我的目标是在 OpenCV 中获取图像的DFT。 使用 dft 函数,我能够计算它,然后通过计算它的大小来绘制它(然后,应用对数并最终对其进行归一化,以便绘制介于 0 和 1 之间的值) . 我的结果
我正在从事一个 Python 项目,该项目模拟振动弦产生的声音。如果对于给定的字符串,我已经确定了运动的傅里叶变换,则可以通过简单的操作将这些结果更改为显示每个(音频)频率幅度的数据。 是否可以使用
我使用 apache commons 数学库来转换我的音频样本缓冲区上的 FFt 和 IFFT。 FFT 的输出给了我一组复数。频率在中间镜像。样本缓冲区大小为 4096 个样本,我得到 2048 个
我是一名优秀的程序员,十分优秀!