Повышение производительности потоков и SwingWorker для построения графиков БПФ - PullRequest
0 голосов
/ 28 апреля 2018

Я занимаюсь разработкой приложения для проверки концепции с использованием Java. Я заметил, что мое Java-приложение работает медленнее, чем версия CSharp, когда я его запускаю. Я хочу концепцию или предложение по улучшению производительности.

Я записываю звук со своего микрофона, используя одну тему, внутри этой темы у меня есть другие темы:

  • Чтобы сохранить байты звука на жестком диске,
  • Другой способ отображения байтов (отсчетов) во времени и БПФ (быстрое преобразование Фурье).

enter image description here К сожалению, код очень длинный и SSCCE (очень сложно извлечь функциональный код для размещения короткого кода).

Мой код опубликован в Git , и я сделал видео , чтобы показать его производительность.

  1. Я хочу знать легкую библиотеку Java (тип диаграммы), которая отображает или отображает мое время и БПФ много раз каждую секунду.
  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();
      }
    
...