提高线程和SwingWorker的性能以绘制FFT图表

时间:2018-04-28 01:33:10

标签: java multithreading charts fft swingworker

我正在使用Java开发概念验证应用程序。我注意到,当我运行它时,我的Java应用程序比CSharp版本要慢。我想要一个概念或建议来改善表现。

我从我的麦克风中捕获声音,使用一个线程,在此线程中,我有另一个线程:

  • 要在硬盘上保存声音字节,
  • 另一个用时间和FFT(快速傅立叶变换)绘制字节(样本)。

enter image description here 不幸的是,代码很长而且SSCCE(很难提取功能代码,以便发布短代码)。

我的代码是Git中的帖子,我做了video以显示其效果。

  1. 我想知道轻型Java库(图表类型),用于绘制或绘制我的时间和FFT每秒更改次数。
  2. 我想要一些建议来发现我对这段代码的逻辑缺陷。

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

0 个答案:

没有答案