diff --git a/pom.xml b/pom.xml
index d7ae9ef..31a5f1c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
sh.ball
osci-render
- 1.18.0
+ 1.18.1
osci-render
diff --git a/src/main/java/sh/ball/audio/ShapeAudioPlayer.java b/src/main/java/sh/ball/audio/ShapeAudioPlayer.java
index d6b4c8a..95085b4 100644
--- a/src/main/java/sh/ball/audio/ShapeAudioPlayer.java
+++ b/src/main/java/sh/ball/audio/ShapeAudioPlayer.java
@@ -91,7 +91,7 @@ public class ShapeAudioPlayer implements AudioPlayer> {
communicator.addListener(this);
}
- private void resetMidi() {
+ public void resetMidi() {
keysDown.clear();
for (int i = 0; i < keyTargetVolumes.length; i++) {
Arrays.fill(keyTargetVolumes[i], (short) 0);
@@ -102,6 +102,7 @@ public class ShapeAudioPlayer implements AudioPlayer> {
keyActualVolumes[0][60] = (short) MidiNote.MAX_VELOCITY;
keysDown.add(new MidiNote(60));
midiStarted = false;
+ notesChanged();
}
public void stopMidiNotes() {
@@ -118,6 +119,11 @@ public class ShapeAudioPlayer implements AudioPlayer> {
public void setVolume(DoubleProperty volume) {
this.volume = Objects.requireNonNullElseGet(volume, () -> new SimpleDoubleProperty(1));
+ this.volume.addListener(e -> {
+ if (keysDown.size() == 0) {
+ resetMidi();
+ }
+ });
}
private Vector2 generateChannels() throws InterruptedException {
@@ -477,6 +483,7 @@ public class ShapeAudioPlayer implements AudioPlayer> {
return;
}
}
+
}
public void setTrace(double trace) {
@@ -489,7 +496,8 @@ public class ShapeAudioPlayer implements AudioPlayer> {
return;
}
int command = message.getCommand();
- if (!midiStarted) {
+
+ if (!midiStarted && (command == ShortMessage.NOTE_ON || command == ShortMessage.NOTE_OFF)) {
stopMidiNotes();
midiStarted = true;
}
diff --git a/src/main/java/sh/ball/audio/effect/TranslateEffect.java b/src/main/java/sh/ball/audio/effect/TranslateEffect.java
index b862f1d..55576e2 100644
--- a/src/main/java/sh/ball/audio/effect/TranslateEffect.java
+++ b/src/main/java/sh/ball/audio/effect/TranslateEffect.java
@@ -8,6 +8,7 @@ public class TranslateEffect extends PhaseEffect {
private Vector2 translation;
private boolean ellipse = false;
+ private double scale;
public TranslateEffect(int sampleRate, double speed, Vector2 translation) {
super(sampleRate, speed);
@@ -22,9 +23,9 @@ public class TranslateEffect extends PhaseEffect {
public Vector2 apply(int count, Vector2 vector) {
if (ellipse) {
double theta = nextTheta();
- return vector.translate(translation.scale(new Vector2(Math.sin(theta), Math.cos(theta))));
+ return vector.translate(translation.scale(new Vector2(Math.sin(theta), Math.cos(theta))).scale(scale));
} else {
- return vector.translate(translation);
+ return vector.translate(translation.scale(scale));
}
}
@@ -38,4 +39,8 @@ public class TranslateEffect extends PhaseEffect {
}
this.ellipse = ellipse;
}
+
+ public void setScale(double scale) {
+ this.scale = scale;
+ }
}
diff --git a/src/main/java/sh/ball/gui/controller/ImageController.java b/src/main/java/sh/ball/gui/controller/ImageController.java
index 40eeecc..1286718 100644
--- a/src/main/java/sh/ball/gui/controller/ImageController.java
+++ b/src/main/java/sh/ball/gui/controller/ImageController.java
@@ -51,6 +51,10 @@ public class ImageController implements Initializable, SubController {
@FXML
private CheckBox translateCheckBox;
@FXML
+ private Slider translationScaleSlider;
+ @FXML
+ private SVGPath translationScaleMidi;
+ @FXML
private Slider frequencySlider;
@FXML
private SVGPath frequencyMidi;
@@ -133,6 +137,8 @@ public class ImageController implements Initializable, SubController {
translateEllipseCheckBox.selectedProperty().addListener((e, old, ellipse) -> translateEffect.setEllipse(ellipse));
+ translationScaleSlider.valueProperty().addListener((e, old, scale) -> translateEffect.setScale(scale.doubleValue()));
+
// converts the value of frequencySlider to the actual frequency that it represents so that it
// can increase at an exponential scale.
frequencySlider.valueProperty().addListener((o, old, f) -> frequency.set(Math.pow(MAX_FREQUENCY, f.doubleValue())));
@@ -150,20 +156,21 @@ public class ImageController implements Initializable, SubController {
rotateSpeedMidi, rotateSpeedSlider,
translationSpeedMidi, translationSpeedSlider,
volumeMidi, volumeSlider,
- visibilityMidi, visibilitySlider
+ visibilityMidi, visibilitySlider,
+ translationScaleMidi, translationScaleSlider
);
}
@Override
public List sliders() {
return List.of(frequencySlider, rotateSpeedSlider, translationSpeedSlider,
- volumeSlider, visibilitySlider);
+ volumeSlider, visibilitySlider, translationScaleSlider);
}
@Override
public List labels() {
return List.of("frequency", "rotateSpeed", "translationSpeed", "volume",
- "visibility");
+ "visibility", "translationScale");
}
@Override
diff --git a/src/main/java/sh/ball/gui/controller/MainController.java b/src/main/java/sh/ball/gui/controller/MainController.java
index eed6edf..e558436 100644
--- a/src/main/java/sh/ball/gui/controller/MainController.java
+++ b/src/main/java/sh/ball/gui/controller/MainController.java
@@ -102,6 +102,8 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
@FXML
private MenuItem stopMidiNotesMenuItem;
@FXML
+ private MenuItem resetMidiMenuItem;
+ @FXML
private Spinner midiChannelSpinner;
public MainController() throws Exception {
@@ -198,8 +200,8 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
});
resetMidiMappingMenuItem.setOnAction(e -> resetCCMap());
-
stopMidiNotesMenuItem.setOnAction(e -> audioPlayer.stopMidiNotes());
+ resetMidiMenuItem.setOnAction(e -> audioPlayer.resetMidi());
NumberFormat format = NumberFormat.getIntegerInstance();
UnaryOperator filter = c -> {
@@ -489,8 +491,12 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
private void loadSliderValues(List sliders, List labels, Element root) {
for (int i = 0; i < sliders.size(); i++) {
- String value = root.getElementsByTagName(labels.get(i)).item(0).getTextContent();
- sliders.get(i).setValue(Float.parseFloat(value));
+ NodeList nodes = root.getElementsByTagName(labels.get(i));
+ // backwards compatibility
+ if (nodes.getLength() > 0) {
+ String value = nodes.item(0).getTextContent();
+ sliders.get(i).setValue(Float.parseFloat(value));
+ }
}
}
@@ -581,6 +587,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
resetCCMap();
for (int i = 0; i < labels.size(); i++) {
NodeList elements = midiElement.getElementsByTagName(labels.get(i));
+ // backwards compatibility
if (elements.getLength() > 0) {
Element midi = (Element) elements.item(0);
int cc = Integer.parseInt(midi.getTextContent());
diff --git a/src/main/resources/fxml/image.fxml b/src/main/resources/fxml/image.fxml
index f353048..508b96a 100644
--- a/src/main/resources/fxml/image.fxml
+++ b/src/main/resources/fxml/image.fxml
@@ -8,28 +8,28 @@
-
+
-
-
diff --git a/src/main/resources/fxml/main.fxml b/src/main/resources/fxml/main.fxml
index 49a16dd..63382d3 100644
--- a/src/main/resources/fxml/main.fxml
+++ b/src/main/resources/fxml/main.fxml
@@ -43,6 +43,7 @@
+