Java 通过绘制FFT图提高线程和SwingWorker的性能
我正在使用Java开发一个概念验证应用程序。我注意到,与运行CSharp的版本相比,我的Java应用程序速度较慢。我想要一个概念或建议来提高性能 我用一个线程从麦克风捕捉声音,在这个线程中,我有另一个线程:Java 通过绘制FFT图提高线程和SwingWorker的性能,java,multithreading,charts,fft,swingworker,Java,Multithreading,Charts,Fft,Swingworker,我正在使用Java开发一个概念验证应用程序。我注意到,与运行CSharp的版本相比,我的Java应用程序速度较慢。我想要一个概念或建议来提高性能 我用一个线程从麦克风捕捉声音,在这个线程中,我有另一个线程: 要在硬盘上保存声音字节 另一种方法是在时间和FFT(快速傅立叶变换)中绘制字节(样本) 不幸的是,代码很长,SSCCE(很难提取功能代码,以便发布短代码) 我的代码是发布的,为了显示它的性能,我做了一个测试 我想知道light Java库(图表类型),以绘制或绘制我的时间和FFT每秒变
- 要在硬盘上保存声音字节
- 另一种方法是在时间和FFT(快速傅立叶变换)中绘制字节(样本)
final AudioFormat audioformat = new AudioFormat(16000 /*Frequency*/,
16 /* two bytes per sample */, 2 /*Stereo*/, true /*Signed*/, true /*bigEndian*/);
final DataLine.Info dlInfo = new DataLine.Info(TargetDataLine.class, audioformat);
if (!AudioSystem.isLineSupported(dlInfo)) {
System.out.println("Line not supported");
}
try {
final TargetDataLine tdLine = (TargetDataLine) AudioSystem.getLine(dlInfo);
if (jtbCapture.isSelected()) {
fileRecordedWav = new File("Some/Path/Filename.wav");
final AudioFileFormat.Type afType = AudioFileFormat.Type.WAVE;
thrdRecording = new Thread() {
@Override
public void run() {
try {
tdLine.open(audioformat);
int bufferSize = (int) audioformat.getSampleRate()
* audioformat.getFrameSize(); //1Sec/40 = 25 milli Second
System.out.println("bufferSize:" + bufferSize);
//INI Save File
final PipedOutputStream SrcSavePOStream = new PipedOutputStream();
final PipedInputStream SnkSavePIStream = new PipedInputStream();
SnkSavePIStream.connect(SrcSavePOStream);
aisRecording = new AudioInputStream((InputStream)SnkSavePIStream,
audioformat, AudioSystem.NOT_SPECIFIED);
Runnable runnableSave = () -> {
try {
AudioSystem.write(aisRecording, afType, fileRecordedWav);
} catch (IOException ex) { /*Pipe broken*/}
};
Thread threadSave = new Thread(runnableSave);
threadSave.start();
//END Save File
// INI Graph File
final PipedOutputStream SrcPlotPOStream = new PipedOutputStream();
final PipedInputStream SnkPlotPIStream = new PipedInputStream();
SnkPlotPIStream.connect(SrcPlotPOStream);
Runnable runnablePlot = () -> {
try {
int qtyBytes;
byte[] incomingBytes = new byte[bufferSize];
int numBytesPerSample = audioformat.getSampleSizeInBits()/8;
int numChannels = audioformat.getChannels();
int frameSize = audioformat.getFrameSize();
int bytesframeSize = numBytesPerSample*numChannels;
Double sampleRateTime = (double)audioformat.getSampleRate();
while ((qtyBytes = SnkPlotPIStream.read(incomingBytes)) != -1) {
byte[] bytesSamples = new byte[qtyBytes];
System.arraycopy(incomingBytes, 0, bytesSamples, 0, qtyBytes);
int qtySamples = qtyBytes/frameSize;
double[] samplesTime = getSamplesBuffer(bytesSamples,
numBytesPerSample, numChannels, "left", 0, qtySamples);
double pow = Math.floor(Math.log(qtySamples) / Math.log(2.0));
int sizePower2 = (int)Math.pow(2.0, pow);
double[] freqs = new double[qtySamples];
double[] samplesPower2 = new double[sizePower2];
System.arraycopy(samplesTime, 0, samplesPower2, 0, sizePower2);
double[] time = new double[qtySamples];
double counter = 0.0;
for (int i = 0; i < time.length; i++) {
time[i] = counter / sampleRateTime;//
counter++;
freqs[i] = (double)i/qtySamples*sampleRateTime/1000.0;
}
// INI Time
SwingWorker swingWorkerPlotTime = new SwingWorker() {
PanelChart panelChartTimeSound = new PanelChart();
@Override protected Void doInBackground() throws Exception {
panelChartTimeSound.addVble("sound", time, samplesTime, Color.GREEN);
return null;
}
@Override protected void done() {
if (panelChartTimeSound.hasPlottable()) {
setPanelInPanel(jpMakeSoundTime,
panelChartTimeSound.getChart(jpMakeSoundTime.getWidth(), jpMakeSoundTime.getHeight()));
panelChartTimeSound.delAllVble();
panelChartTimeSound = null;
}
}
};
swingWorkerPlotTime.execute();
// END Time
// INI FFT
double[] fft = FourierTransform.customFFT(samplesPower2);
double[] halfFFT = new double[sizePower2/2];
double[] halfFreq = new double[sizePower2/2];
System.arraycopy(freqs, 0, halfFreq, 0, halfFreq.length);
System.arraycopy(fft, 0, halfFFT, 0, halfFFT.length);
SwingWorker swingWorkerPlotFreq = new SwingWorker() {
PanelChart panelChartFreqSound = new PanelChart();
@Override protected Void doInBackground() throws Exception {
panelChartFreqSound.addVble("sound", halfFreq, halfFFT, new Color(0, 255, 192));
return null;
}
@Override protected void done() {
if (panelChartFreqSound.hasPlottable()) {
setPanelInPanel(jpMakeSoundFFT,
panelChartFreqSound.getChart(jpMakeSoundFFT.getWidth(), jpMakeSoundFFT.getHeight()));
panelChartFreqSound.delAllVble();
panelChartFreqSound = null;
}
}
};
swingWorkerPlotFreq.execute();
// END FFT
}
} catch (IOException ex) {
System.out.println("runnablePlot:" + ex.toString());
}
};
Thread threadPlot = new Thread(runnablePlot);
threadPlot.start();
// END Graph File
// INI Microphone Capture
byte[] buffer = new byte[bufferSize];
tdLine.start();
while (true) {
int count = tdLine.read(buffer, 0, buffer.length);
if (count > 0) {
SrcSavePOStream.write(buffer);
SrcPlotPOStream.write(buffer);
}
}
// END Microphone Capture
} catch (LineUnavailableException | IOException ex) {
System.out.println("thrdRecording.run:" + ex.toString());
}
}
};
thrdRecording.start();
}
final AudioFormat AudioFormat=新的AudioFormat(16000/*频率*/,,
16/*每个样本两个字节*/,2/*立体声*/,真/*带符号*/,真/*双端*/);
final DataLine.Info dlInfo=新的DataLine.Info(TargetDataLine.class,audioformat);
如果(!AudioSystem.isLineSupported(dlInfo)){
System.out.println(“不支持行”);
}
试一试{
最终TargetDataLine tdLine=(TargetDataLine)AudioSystem.getLine(dlInfo);
if(jtbCapture.isSelected()){
fileRecordedWav=新文件(“Some/Path/Filename.wav”);
最终AudioFileFormat.Type afType=AudioFileFormat.Type.WAVE;
thrdRecording=新线程(){
@凌驾
公开募捐{
试一试{
tdLine.open(音频格式);
int bufferSize=(int)audioformat.getSampleRate()
*audioformat.getFrameSize();//1秒/40=25毫秒
System.out.println(“bufferSize:+bufferSize”);
//INI保存文件
final PipedOutputStream SrcSavePOStream=新的PipedOutputStream();
最终PipedInputStream SnkSavePIStream=新PipedInputStream();
SnkSavePIStream.connect(SrcSavePOStream);
AIS录制=新的音频输入流((输入流)SnkSavePIStream,
音频格式,音频系统。未指定);
Runnable runnableSave=()->{
试一试{
音频系统。写入(AIS录制、afType、fileRecordedWav);
}捕获(IOException ex){/*管道断裂*/}
};
Thread threadSave=新线程(runnableSave);
threadSave.start();
//结束保存文件
//INI图形文件
最终管道输出流SrcPlotPOStream=新管道输出流();
最终PipedInputStream SnkPlotPIStream=新的PipedInputStream();
SnkPlotPIStream.connect(SrcPlotPOStream);
Runnable runnablePlot=()->{
试一试{
int-qtyBytes;
字节[]incomingBytes=新字节[bufferSize];
int numBytesPerSample=audioformat.getSampleSizeInBits()/8;
int numChannels=audioformat.getChannels();
int frameSize=audioformat.getFrameSize();
int bytesframeSize=numbytes样本*numChannels;
Double sampleRateTime=(Double)audioformat.getSampleRate();
而((qtyBytes=SnkPlotPIStream.read(incomingBytes))!=-1){
byte[]bytesamples=新字节[qtyBytes];
数组复制(incomingBytes,0,bytesamples,0,qtyBytes);
int-qtySamples=qtyBytes/frameSize;
double[]samplesTime=getSamplesBuffer(bytesSamples,
numBytesPerSample,NumChannel,“左”,0,qtySamples);
double-pow=Math.floor(Math.log(qtySamples)/Math.log(2.0));
int-sizePower2=(int)Math.pow(2.0,pow);
double[]freqs=新的double[qtySamples];
double[]samplesPower2=新的double[sizePower2];
System.arraycopy(samplesTime,0,samplesPower2,0,sizePower2);
double[]时间=新的double[qtySamples];
双计数器=0.0;
for(int i=0;i