【发布时间】:2017-09-13 09:11:08
【问题描述】:
我对声音数字化了解不多。我试图代表麦克风输入的即时配置文件。我知道如何从麦克风中获取信息,但我不知道如何将其解释为配置文件。谁能帮我填空?
package test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.OutputStream;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
*
* @author François Billioud
*/
public class SoundRecorder extends JFrame {
/** JFrame for the GUI **/
public SoundRecorder() {
super("Sound Recorder");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = getContentPane();
pane.setLayout(new BorderLayout());
pane.add(wavePane = new WavePane(), BorderLayout.CENTER);
pane.add(new JButton(new AbstractAction("ok") {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
}
}), BorderLayout.SOUTH);
setSize(300,300);
setLocationRelativeTo(null);
}
/** Just displays the frame and starts listening **/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SoundRecorder rec = new SoundRecorder();
rec.setVisible(true);
rec.listenToMic();
}
});
}
/** Draws the sound read from the mic **/
private static class WavePane extends JPanel {
private final int[] x = new int[0];
private int[] y = new int[0];
private WavePane() {
setOpaque(true);
setBackground(Color.WHITE);
}
/** updates the data to be displayed **/
public void setData(int[] y) {
this.y = y;
int n = y.length;
this.x = new int[n];
float pas = getWidth()/(float)(n-1);
float xCurrent = 0;
for(int i=0; i<n; i++) {
this.x[i] = Math.round(xCurrent);
xCurrent+=pas;
}
repaint();
}
/** Draws a line that represent the mic profile **/
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2D.drawPolyline(x, y, x.length);
}
}
/** Defines the audio format to be used.
* I know nothing about that and am open to suggestions if needed
*/
private static final AudioFormat format = new AudioFormat(
16000, //Sample rate
16, //SampleSizeInBits
2, //Channels
true,//Signed
true //BigEndian
);
/** Creates a thread that will read data from
* the mic and send it to the WavePane
* in order to be painted.
* We should be using a SwingWorker, but it will do
* for the sake of this demo.
**/
private void listenToMic() {
new Thread(new Runnable() {
@Override
public void run() {
try {
//Open the line and read
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
//checks if system supports the data line
if (!AudioSystem.isLineSupported(info)) {
System.err.print("Line not supported");
}
//starts listening
TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();
//sends the stream to the interpreter
AudioInputStream ais = new AudioInputStream(line);
AudioSystem.write(ais, AudioFileFormat.Type.AU, new Interpreter());
} catch (LineUnavailableException | IOException ex) {
System.err.println(ex.getLocalizedMessage());
}
}
}).start();
}
private final WavePane wavePane;
private class Interpreter extends OutputStream {
private int[] y;
@Override
public void write(int b) throws IOException {
//TBD
//Fill y array
}
@Override
public void flush() throws IOException {
//Sends the values found to the panel for drawing
wavePane.setData(y);
}
}
}
我找到了this link,但对我没有帮助...
编辑:好的,据我了解,每 16 位是一个频率的幅度。我有 2 个通道,所以我必须每 32 读取 16 位才能获得第一个通道。现在我需要知道每帧要读取多少个频率。然后我想我可以画出轮廓。有什么提示吗?
【问题讨论】: