diff options
Diffstat (limited to 'src/main/java/com/jsyn/scope/swing')
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); + } + } + } + } + } + +} |