0

I have an array of 100,000 samples all of double type. I want to display or plot this array so that I get a moving chart/ plot (dynamic) instead of displaying it at once. Can anyone help me out. In plot ee[] and y[] is obtained after some processing.

private byte[] FileR(String filename) {
    byte[] data = null;
    AudioInputStream ais;
    try {
        File fileIn = new File(filename);
        if (fileIn.exists()) {
            ais = AudioSystem.getAudioInputStream(fileIn);
            data = new byte[ais.available()];
            ais.read(data);
        }
    } catch (UnsupportedAudioFileException | IOException e) {
        System.out.println(e.getMessage());
        throw new RuntimeException("Could not read " + filename);
    }
    return data;
}

private byte[] Capture(double t) throws LineUnavailableException {
    AudioFormat format = new AudioFormat(48000, 16, 2, true, false);
    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
    line = (TargetDataLine) AudioSystem.getLine(info);
    line.open(format);
    line.open();
    int size = (int) (line.getBufferSize() * t);
    byte[] b = new byte[size];
    line.start();
    line.read(b, 0, size);
    return b;
}

private void plot(double[] ee, double[] y) {
    XYSeries see = new XYSeries("Filtered");
    for (int i = 0; i < ee.length; i++) {
        see.add(i, ee[i]);
    }
    XYSeriesCollection cee = new XYSeriesCollection();
    cee.addSeries(see);
    XYItemRenderer ree = new StandardXYItemRenderer();
    NumberAxis rangeAxisee = new NumberAxis("Filtered");
    XYPlot subplot1 = new XYPlot(cee, null, rangeAxisee, ree);
    subplot1.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
    XYSeries sy = new XYSeries("Noisy");
    for (int i = 0; i < y.length; i++) {
        sy.add(i, y[i]);
    }
    XYSeriesCollection cy = new XYSeriesCollection();
    cy.addSeries(sy);
    XYItemRenderer ry = new StandardXYItemRenderer();
    NumberAxis rangeAxisy = new NumberAxis("Noisy");
    XYPlot subplot2 = new XYPlot(cy, null, rangeAxisy, ry);
    subplot2.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
    CombinedDomainXYPlot plot = new CombinedDomainXYPlot(new NumberAxis("Domain"));
    plot.setGap(10.0);
    plot.add(subplot1);
    plot.add(subplot2);
    plot.setOrientation(PlotOrientation.VERTICAL);
    JFreeChart chart = new JFreeChart("Adaptive Filter", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
    panel = new ChartPanel(chart, true, true, true, false, true);
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(750, 500);
    frame.add(panel, BorderLayout.CENTER);
    frame.setVisible(true);
}
Oliver Watkins
  • 12,575
  • 33
  • 119
  • 225

1 Answers1

0

You need to have a thread where all this data is coming from. For example from your backend. Then, every time there is a new set of data for the chart you will need to update the chart via the Event Dispatch Thread. If your chart data is coming in regular intervals it is fairly easy (ie. pull), however if it is push (ie. the data is more random), and can get a little more tricky.

Remove all the GUI creation out of the plot method :

JFreeChart chart = new JFreeChart("Adaptive Filter", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
panel = new ChartPanel(chart, true, true, true, false, true);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(750, 500);
frame.add(panel, BorderLayout.CENTER);
frame.setVisible(true);

This only needs to be called once. The plot method will be called every time new data comes.

Here is a simple approach :

public void startCharting() {

    final MySoundCard card = new MySoundCard();
    final MyJFreeChart chart = new MyJFreeChart();

    Runnable r = new Runnable() {

        @Override
        public void run() {
            while(true) {

                int[] i = card.FileR();


                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {

                        chart.plot();
                    }

                });


                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    };

    Thread t = new Thread(r);
    t.start();
}

A thread calls your datasource every second and then updates the chart. The updates are invoked in the Event Dispatch Thread.

Oliver Watkins
  • 12,575
  • 33
  • 119
  • 225
  • The data (Array of samples) received from an audio file or captured from the sound card. Now I want to display that one in a moving fashion (dynamic - not in time series) instead of displaying in one go. If possible exemplify please. – Abdul Baseer Buriro Jul 10 '13 at 10:49
  • Firstly how is your data coming into your application. Are you calling a method? Or is the data being captured somehow in your application? – Oliver Watkins Jul 10 '13 at 11:15
  • @AbdulBaseerBuriro I added some code which should give you an idea. – Oliver Watkins Jul 10 '13 at 11:27
  • Data is coming through a method call. One method is to get a data from a file and second gets from the card. This is based on user's selection. – Abdul Baseer Buriro Jul 10 '13 at 13:27
  • @AbdulBaseerBuriro you should paste some code in your question. Can't really help you much more than that. – Oliver Watkins Jul 10 '13 at 13:33