aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/com/jsyn/scope/swing
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/jsyn/scope/swing')
-rw-r--r--src/main/java/com/jsyn/scope/swing/AudioScopeProbeView.java45
-rw-r--r--src/main/java/com/jsyn/scope/swing/AudioScopeView.java112
-rw-r--r--src/main/java/com/jsyn/scope/swing/MultipleWaveDisplay.java58
-rw-r--r--src/main/java/com/jsyn/scope/swing/ScopeControlPanel.java46
-rw-r--r--src/main/java/com/jsyn/scope/swing/ScopeProbePanel.java87
-rw-r--r--src/main/java/com/jsyn/scope/swing/ScopeTriggerPanel.java47
-rw-r--r--src/main/java/com/jsyn/scope/swing/WaveTraceView.java122
7 files changed, 517 insertions, 0 deletions
diff --git a/src/main/java/com/jsyn/scope/swing/AudioScopeProbeView.java b/src/main/java/com/jsyn/scope/swing/AudioScopeProbeView.java
new file mode 100644
index 0000000..59526e1
--- /dev/null
+++ b/src/main/java/com/jsyn/scope/swing/AudioScopeProbeView.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2010 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.scope.swing;
+
+import com.jsyn.scope.AudioScopeProbe;
+
+/**
+ * Wave display associated with a probe.
+ *
+ * @author Phil Burk (C) 2010 Mobileer Inc
+ */
+public class AudioScopeProbeView {
+ private AudioScopeProbe probeModel;
+ private WaveTraceView waveTrace;
+
+ public AudioScopeProbeView(AudioScopeProbe probeModel) {
+ this.probeModel = probeModel;
+ waveTrace = new WaveTraceView(probeModel.getAutoScaleButtonModel(),
+ probeModel.getVerticalScaleModel());
+ waveTrace.setModel(probeModel.getWaveTraceModel());
+ }
+
+ public WaveTraceView getWaveTraceView() {
+ return waveTrace;
+ }
+
+ public AudioScopeProbe getModel() {
+ return probeModel;
+ }
+
+}
diff --git a/src/main/java/com/jsyn/scope/swing/AudioScopeView.java b/src/main/java/com/jsyn/scope/swing/AudioScopeView.java
new file mode 100644
index 0000000..ec1afa3
--- /dev/null
+++ b/src/main/java/com/jsyn/scope/swing/AudioScopeView.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2009 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.scope.swing;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.util.ArrayList;
+
+import javax.swing.JPanel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import com.jsyn.scope.AudioScopeModel;
+import com.jsyn.scope.AudioScopeProbe;
+
+public class AudioScopeView extends JPanel {
+ private static final long serialVersionUID = -7507986850757860853L;
+ private AudioScopeModel audioScopeModel;
+ private ArrayList<AudioScopeProbeView> probeViews = new ArrayList<AudioScopeProbeView>();
+ private MultipleWaveDisplay multipleWaveDisplay;
+ private boolean showControls = false;
+ private ScopeControlPanel controlPanel = null;
+
+ public AudioScopeView() {
+ setBackground(Color.GREEN);
+ }
+
+ public void setModel(AudioScopeModel audioScopeModel) {
+ this.audioScopeModel = audioScopeModel;
+ // Create a view for each probe.
+ probeViews.clear();
+ for (AudioScopeProbe probeModel : audioScopeModel.getProbes()) {
+ AudioScopeProbeView audioScopeProbeView = new AudioScopeProbeView(probeModel);
+ probeViews.add(audioScopeProbeView);
+ }
+ setupGUI();
+
+ // Listener for signal change events.
+ audioScopeModel.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ multipleWaveDisplay.repaint();
+ }
+ });
+
+ }
+
+ private void setupGUI() {
+ removeAll();
+ setLayout(new BorderLayout());
+ multipleWaveDisplay = new MultipleWaveDisplay();
+
+ for (AudioScopeProbeView probeView : probeViews) {
+ multipleWaveDisplay.addWaveTrace(probeView.getWaveTraceView());
+ probeView.getModel().setColor(probeView.getWaveTraceView().getColor());
+ }
+
+ add(multipleWaveDisplay, BorderLayout.CENTER);
+
+ setMinimumSize(new Dimension(400, 200));
+ setPreferredSize(new Dimension(600, 250));
+ setMaximumSize(new Dimension(1200, 300));
+ }
+
+ /** @deprecated Use setControlsVisible() instead. */
+ @Deprecated
+ public void setShowControls(boolean show) {
+ setControlsVisible(show);
+ }
+
+ public void setControlsVisible(boolean show) {
+ if (this.showControls) {
+ if (!show && (controlPanel != null)) {
+ remove(controlPanel);
+ }
+ } else {
+ if (show) {
+ if (controlPanel == null) {
+ controlPanel = new ScopeControlPanel(this);
+ }
+ add(controlPanel, BorderLayout.EAST);
+ validate();
+ }
+ }
+
+ this.showControls = show;
+ }
+
+ public AudioScopeModel getModel() {
+ return audioScopeModel;
+ }
+
+ public AudioScopeProbeView[] getProbeViews() {
+ return probeViews.toArray(new AudioScopeProbeView[0]);
+ }
+
+}
diff --git a/src/main/java/com/jsyn/scope/swing/MultipleWaveDisplay.java b/src/main/java/com/jsyn/scope/swing/MultipleWaveDisplay.java
new file mode 100644
index 0000000..0259850
--- /dev/null
+++ b/src/main/java/com/jsyn/scope/swing/MultipleWaveDisplay.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.scope.swing;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.util.ArrayList;
+
+import javax.swing.JPanel;
+
+/**
+ * Display multiple waveforms together in different colors.
+ *
+ * @author Phil Burk (C) 2011 Mobileer Inc
+ */
+public class MultipleWaveDisplay extends JPanel {
+ private static final long serialVersionUID = -5157397030540800373L;
+
+ private ArrayList<WaveTraceView> waveTraceViews = new ArrayList<WaveTraceView>();
+ private Color[] defaultColors = {
+ Color.BLUE, Color.RED, Color.BLACK, Color.MAGENTA, Color.GREEN, Color.ORANGE
+ };
+
+ public MultipleWaveDisplay() {
+ setBackground(Color.WHITE);
+ }
+
+ public void addWaveTrace(WaveTraceView waveTraceView) {
+ if (waveTraceView.getColor() == null) {
+ waveTraceView.setColor(defaultColors[waveTraceViews.size() % defaultColors.length]);
+ }
+ waveTraceViews.add(waveTraceView);
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ int width = getWidth();
+ int height = getHeight();
+ for (WaveTraceView waveTraceView : waveTraceViews.toArray(new WaveTraceView[0])) {
+ waveTraceView.drawWave(g, width, height);
+ }
+ }
+}
diff --git a/src/main/java/com/jsyn/scope/swing/ScopeControlPanel.java b/src/main/java/com/jsyn/scope/swing/ScopeControlPanel.java
new file mode 100644
index 0000000..7f3a026
--- /dev/null
+++ b/src/main/java/com/jsyn/scope/swing/ScopeControlPanel.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2009 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.scope.swing;
+
+import java.awt.GridLayout;
+
+import javax.swing.JPanel;
+
+import com.jsyn.scope.AudioScopeModel;
+
+public class ScopeControlPanel extends JPanel {
+ private static final long serialVersionUID = 7738305116057614812L;
+ private AudioScopeModel audioScopeModel;
+ private ScopeTriggerPanel triggerPanel;
+ private JPanel probeRows;
+
+ public ScopeControlPanel(AudioScopeView audioScopeView) {
+ setLayout(new GridLayout(0, 1));
+ this.audioScopeModel = audioScopeView.getModel();
+ triggerPanel = new ScopeTriggerPanel(audioScopeModel);
+ add(triggerPanel);
+
+ probeRows = new JPanel();
+ probeRows.setLayout(new GridLayout(1, 0));
+ add(probeRows);
+ for (AudioScopeProbeView probeView : audioScopeView.getProbeViews()) {
+ ScopeProbePanel probePanel = new ScopeProbePanel(probeView);
+ probeRows.add(probePanel);
+ }
+ }
+
+}
diff --git a/src/main/java/com/jsyn/scope/swing/ScopeProbePanel.java b/src/main/java/com/jsyn/scope/swing/ScopeProbePanel.java
new file mode 100644
index 0000000..a0dec91
--- /dev/null
+++ b/src/main/java/com/jsyn/scope/swing/ScopeProbePanel.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2009 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.scope.swing;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+import javax.swing.JToggleButton.ToggleButtonModel;
+
+import com.jsyn.scope.AudioScopeProbe;
+import com.jsyn.swing.RotaryTextController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ScopeProbePanel extends JPanel {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ScopeProbePanel.class);
+ private static final long serialVersionUID = 4511589171299298548L;
+
+ private AudioScopeProbeView audioScopeProbeView;
+ private AudioScopeProbe audioScopeProbe;
+ private RotaryTextController verticalScaleKnob;
+ private JCheckBox autoBox;
+ private ToggleButtonModel autoScaleModel;
+
+ public ScopeProbePanel(AudioScopeProbeView probeView) {
+ this.audioScopeProbeView = probeView;
+ setLayout(new BorderLayout());
+
+ setBorder(BorderFactory.createLineBorder(Color.GRAY, 3));
+
+ // Add a colored box to match the waveform color.
+ JPanel colorPanel = new JPanel();
+ colorPanel.setMinimumSize(new Dimension(40, 40));
+ audioScopeProbe = probeView.getModel();
+ colorPanel.setBackground(audioScopeProbe.getColor());
+ add(colorPanel, BorderLayout.NORTH);
+
+ // Knob for tweaking vertical range.
+ verticalScaleKnob = new RotaryTextController(audioScopeProbeView.getWaveTraceView()
+ .getVerticalRangeModel(), 5);
+ add(verticalScaleKnob, BorderLayout.CENTER);
+ verticalScaleKnob.setTitle("YScale");
+
+ // Auto ranging checkbox.
+ autoBox = new JCheckBox("Auto");
+ autoScaleModel = audioScopeProbeView.getWaveTraceView().getAutoButtonModel();
+ autoScaleModel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ ToggleButtonModel model = (ToggleButtonModel) e.getSource();
+ boolean enabled = !model.isSelected();
+ LOGGER.debug("Knob enabled = " + enabled);
+ verticalScaleKnob.setEnabled(!model.isSelected());
+ }
+ });
+ autoBox.setModel(autoScaleModel);
+ add(autoBox, BorderLayout.SOUTH);
+
+ verticalScaleKnob.setEnabled(!autoScaleModel.isSelected());
+
+ setMinimumSize(new Dimension(80, 100));
+ setPreferredSize(new Dimension(80, 150));
+ setMaximumSize(new Dimension(120, 200));
+ }
+
+}
diff --git a/src/main/java/com/jsyn/scope/swing/ScopeTriggerPanel.java b/src/main/java/com/jsyn/scope/swing/ScopeTriggerPanel.java
new file mode 100644
index 0000000..9c22aa1
--- /dev/null
+++ b/src/main/java/com/jsyn/scope/swing/ScopeTriggerPanel.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.scope.swing;
+
+import java.awt.BorderLayout;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JPanel;
+
+import com.jsyn.scope.AudioScopeModel;
+import com.jsyn.scope.TriggerModel;
+import com.jsyn.scope.AudioScope.TriggerMode;
+import com.jsyn.swing.RotaryTextController;
+
+public class ScopeTriggerPanel extends JPanel {
+ private static final long serialVersionUID = 4511589171299298548L;
+ private JComboBox<DefaultComboBoxModel<TriggerMode>> triggerModeComboBox;
+ private RotaryTextController triggerLevelKnob;
+
+ public ScopeTriggerPanel(AudioScopeModel audioScopeModel) {
+ setLayout(new BorderLayout());
+ TriggerModel triggerModel = audioScopeModel.getTriggerModel();
+ triggerModeComboBox = new JComboBox(triggerModel.getModeModel());
+ add(triggerModeComboBox, BorderLayout.NORTH);
+
+ triggerLevelKnob = new RotaryTextController(triggerModel.getLevelModel(), 5);
+
+ add(triggerLevelKnob, BorderLayout.CENTER);
+ triggerLevelKnob.setTitle("Trigger Level");
+ }
+
+}
diff --git a/src/main/java/com/jsyn/scope/swing/WaveTraceView.java b/src/main/java/com/jsyn/scope/swing/WaveTraceView.java
new file mode 100644
index 0000000..849a6f4
--- /dev/null
+++ b/src/main/java/com/jsyn/scope/swing/WaveTraceView.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2009 Phil Burk, Mobileer Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jsyn.scope.swing;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JToggleButton.ToggleButtonModel;
+
+import com.jsyn.scope.WaveTraceModel;
+import com.jsyn.swing.ExponentialRangeModel;
+
+public class WaveTraceView {
+ private static final double AUTO_DECAY = 0.95;
+ private WaveTraceModel waveTraceModel;
+ private Color color;
+ private ExponentialRangeModel verticalScaleModel;
+ private ToggleButtonModel autoScaleButtonModel;
+
+ private double xScaler;
+ private double yScalar;
+ private int centerY;
+
+ public WaveTraceView(ToggleButtonModel autoButtonModel, ExponentialRangeModel verticalRangeModel) {
+ this.verticalScaleModel = verticalRangeModel;
+ this.autoScaleButtonModel = autoButtonModel;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ public ExponentialRangeModel getVerticalRangeModel() {
+ return verticalScaleModel;
+ }
+
+ public ToggleButtonModel getAutoButtonModel() {
+ return autoScaleButtonModel;
+ }
+
+ public void setModel(WaveTraceModel waveTraceModel) {
+ this.waveTraceModel = waveTraceModel;
+ }
+
+ public int convertRealToY(double r) {
+ return centerY - (int) (yScalar * r);
+ }
+
+ public void drawWave(Graphics g, int width, int height) {
+ double sampleMax = 0.0;
+ double sampleMin = 0.0;
+ g.setColor(color);
+ int numSamples = waveTraceModel.getVisibleSize();
+ if (numSamples > 0) {
+ xScaler = (double) width / numSamples;
+ // Scale by 0.5 because it is bipolar.
+ yScalar = 0.5 * height / verticalScaleModel.getDoubleValue();
+ centerY = height / 2;
+
+ // Calculate position of first point.
+ int x1 = 0;
+ int offset = waveTraceModel.getStartIndex();
+ double value = waveTraceModel.getSample(offset);
+ int y1 = convertRealToY(value);
+
+ // Draw lines to remaining points.
+ for (int i = 1; i < numSamples; i++) {
+ int x2 = (int) (i * xScaler);
+ value = waveTraceModel.getSample(offset + i);
+ int y2 = convertRealToY(value);
+ g.drawLine(x1, y1, x2, y2);
+ x1 = x2;
+ y1 = y2;
+ // measure min and max for auto
+ if (value > sampleMax) {
+ sampleMax = value;
+ } else if (value < sampleMin) {
+ sampleMin = value;
+ }
+ }
+
+ autoScaleRange(sampleMax);
+ }
+ }
+
+ // Autoscale the vertical range.
+ private void autoScaleRange(double sampleMax) {
+ if (autoScaleButtonModel.isSelected()) {
+ double scaledMax = sampleMax * 1.1;
+ double current = verticalScaleModel.getDoubleValue();
+ if (scaledMax > current) {
+ verticalScaleModel.setDoubleValue(scaledMax);
+ } else {
+ double decayed = current * AUTO_DECAY;
+ if (decayed > verticalScaleModel.getMinimum()) {
+ if (scaledMax < decayed) {
+ verticalScaleModel.setDoubleValue(decayed);
+ }
+ }
+ }
+ }
+ }
+
+}