kopia lustrzana https://github.com/jameshball/osci-render
rodzic
f5f9246408
commit
9fdab5a4f1
|
@ -1,3 +1,8 @@
|
||||||
|
- 1.24.1
|
||||||
|
- Various optimisations
|
||||||
|
- Mic-based control is now slightly smoother
|
||||||
|
|
||||||
|
|
||||||
- 1.24.0
|
- 1.24.0
|
||||||
- Add spinners to all effect sliders
|
- Add spinners to all effect sliders
|
||||||
- Add spinner to frequency slider
|
- Add spinner to frequency slider
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<groupId>sh.ball</groupId>
|
<groupId>sh.ball</groupId>
|
||||||
<artifactId>osci-render</artifactId>
|
<artifactId>osci-render</artifactId>
|
||||||
<version>1.24.0</version>
|
<version>1.24.1</version>
|
||||||
|
|
||||||
<name>osci-render</name>
|
<name>osci-render</name>
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
||||||
private final Callable<AudioEngine> audioEngineBuilder;
|
private final Callable<AudioEngine> audioEngineBuilder;
|
||||||
private final BlockingQueue<List<Shape>> frameQueue = new ArrayBlockingQueue<>(BUFFER_SIZE);
|
private final BlockingQueue<List<Shape>> frameQueue = new ArrayBlockingQueue<>(BUFFER_SIZE);
|
||||||
private final Map<Object, Effect> effects = new ConcurrentHashMap<>();
|
private final Map<Object, Effect> effects = new ConcurrentHashMap<>();
|
||||||
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
|
private final Queue<Listener> listeners = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
private AudioEngine audioEngine;
|
private AudioEngine audioEngine;
|
||||||
private ByteArrayOutputStream outputStream;
|
private ByteArrayOutputStream outputStream;
|
||||||
|
@ -223,17 +223,19 @@ public class ShapeAudioPlayer implements AudioPlayer<List<Shape>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector2 cutoff(Vector2 vector) {
|
private Vector2 cutoff(Vector2 vector) {
|
||||||
if (vector.getX() < -1) {
|
double x = vector.x;
|
||||||
vector = vector.setX(-1);
|
double y = vector.y;
|
||||||
} else if (vector.getX() > 1) {
|
if (x < -1) {
|
||||||
vector = vector.setX(1);
|
x = -1;
|
||||||
|
} else if (x > 1) {
|
||||||
|
x = 1;
|
||||||
}
|
}
|
||||||
if (vector.getY() < -1) {
|
if (y < -1) {
|
||||||
vector = vector.setY(-1);
|
y = -1;
|
||||||
} else if (vector.getY() > 1) {
|
} else if (y > 1) {
|
||||||
vector = vector.setY(1);
|
y = 1;
|
||||||
}
|
}
|
||||||
return vector;
|
return new Vector2(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vector2 applyEffects(int frame, Vector2 vector) {
|
private Vector2 applyEffects(int frame, Vector2 vector) {
|
||||||
|
|
|
@ -12,9 +12,7 @@ public class BitCrushEffect implements SettableEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 apply(int count, Vector2 vector) {
|
public Vector2 apply(int count, Vector2 vector) {
|
||||||
double x = vector.getX();
|
return new Vector2(round(vector.x, crush), round(vector.y, crush));
|
||||||
double y = vector.getY();
|
|
||||||
return new Vector2(round(x, crush), round(y, crush));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,8 +39,9 @@ public class WobbleEffect extends PhaseEffect implements FrequencyListener, Sett
|
||||||
@Override
|
@Override
|
||||||
public Vector2 apply(int count, Vector2 vector) {
|
public Vector2 apply(int count, Vector2 vector) {
|
||||||
double theta = nextTheta();
|
double theta = nextTheta();
|
||||||
double x = vector.getX() + volume * Math.sin(frequency * theta);
|
double delta = volume * Math.sin(frequency * theta);
|
||||||
double y = vector.getY() + volume * Math.sin(frequency * theta);
|
double x = vector.x + delta;
|
||||||
|
double y = vector.y + delta;
|
||||||
|
|
||||||
return new Vector2(x, y);
|
return new Vector2(x, y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ import java.util.List;
|
||||||
public class JavaAudioInput implements AudioInput {
|
public class JavaAudioInput implements AudioInput {
|
||||||
|
|
||||||
private static final int DEFAULT_SAMPLE_RATE = 44100;
|
private static final int DEFAULT_SAMPLE_RATE = 44100;
|
||||||
private static final int BUFFER_SIZE = 50;
|
private static final int CHUNK_SIZE = 512;
|
||||||
|
private static final int STEP_SIZE = 32;
|
||||||
// java sound doesn't support anything more than 16 bit :(
|
// java sound doesn't support anything more than 16 bit :(
|
||||||
private static final int BIT_DEPTH = 16;
|
private static final int BIT_DEPTH = 16;
|
||||||
// mono
|
// mono
|
||||||
|
@ -45,17 +46,19 @@ public class JavaAudioInput implements AudioInput {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
microphone.open(format, BUFFER_SIZE);
|
microphone.open(format);
|
||||||
|
|
||||||
// I am well aware this is inefficient - sufficient for the needs of
|
byte[] data = new byte[CHUNK_SIZE];
|
||||||
// modifying sliders
|
|
||||||
byte[] data = new byte[2];
|
|
||||||
microphone.start();
|
microphone.start();
|
||||||
while (!stopped) {
|
while (!stopped) {
|
||||||
microphone.read(data, 0, 2);
|
if (microphone.available() >= CHUNK_SIZE) {
|
||||||
short sample = (short) ((data[1] << 8) + data[0]);
|
microphone.read(data, 0, CHUNK_SIZE);
|
||||||
for (AudioInputListener listener : listeners) {
|
for (int i = 0; i < CHUNK_SIZE / 2; i += 2 * STEP_SIZE) {
|
||||||
listener.transmit((double) sample / Short.MAX_VALUE);
|
short sample = (short) ((data[2 * i + 1] << 8) + data[2 * i]);
|
||||||
|
for (AudioInputListener listener : listeners) {
|
||||||
|
listener.transmit((double) sample / Short.MAX_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
microphone.close();
|
microphone.close();
|
||||||
|
|
|
@ -1109,8 +1109,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
||||||
} else if (sliderValue < slider.getMin()) {
|
} else if (sliderValue < slider.getMin()) {
|
||||||
sliderValue = slider.getMin();
|
sliderValue = slider.getMin();
|
||||||
}
|
}
|
||||||
// TODO: Correctly update frequency spinner!
|
subControllers().forEach(SubController::micSignalReceived);
|
||||||
subControllers().forEach(sub -> sub.micSignalReceived());
|
|
||||||
sliders.get(i).setValue(sliderValue);
|
sliders.get(i).setValue(sliderValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,10 @@ public final class Line extends Shape {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 nextVector(double drawingProgress) {
|
public Vector2 nextVector(double drawingProgress) {
|
||||||
return a.add(b.sub(a).scale(drawingProgress));
|
return new Vector2(
|
||||||
|
a.x + drawingProgress * (b.x - a.x),
|
||||||
|
a.y + drawingProgress * (b.y - a.y)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 getA() {
|
public Vector2 getA() {
|
||||||
|
|
|
@ -61,10 +61,12 @@ public final class Vector2 extends Shape {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 rotate(double theta) {
|
public Vector2 rotate(double theta) {
|
||||||
Vector2 vector = setX(getX() * Math.cos(theta) - getY() * Math.sin(theta));
|
double cosTheta = Math.cos(theta);
|
||||||
vector = vector.setY(getX() * Math.sin(theta) + getY() * Math.cos(theta));
|
double sinTheta = Math.sin(theta);
|
||||||
|
return new Vector2(
|
||||||
return vector;
|
x * cosTheta - y * sinTheta,
|
||||||
|
x * sinTheta + y * cosTheta
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -74,12 +76,12 @@ public final class Vector2 extends Shape {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 scale(Vector2 vector) {
|
public Vector2 scale(Vector2 vector) {
|
||||||
return new Vector2(getX() * vector.getX(), getY() * vector.getY());
|
return new Vector2(x * vector.x, y * vector.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 translate(Vector2 vector) {
|
public Vector2 translate(Vector2 vector) {
|
||||||
return new Vector2(getX() + vector.getX(), getY() + vector.getY());
|
return new Vector2(x + vector.x, y + vector.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,13 +98,12 @@ public final class Vector2 extends Shape {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Vector2 point = (Vector2) obj;
|
Vector2 point = (Vector2) obj;
|
||||||
return round(x, 2) == round(point.x, 2)
|
return x == point.x && y == point.y;
|
||||||
&& round(y, 2) == round(point.y, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(round(x, 2), round(y, 2));
|
return Objects.hash(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Ładowanie…
Reference in New Issue