Added shape interface to clean up code and added ellipse class

pull/35/head
James Ball 2020-02-05 23:47:27 +00:00
rodzic 45b66fa4a5
commit 2b6f2932c7
7 zmienionych plików z 143 dodań i 56 usunięć

Wyświetl plik

@ -1,5 +1,6 @@
package audio;
import shapes.Ellipse;
import shapes.Shapes;
import shapes.Vector;
@ -12,10 +13,11 @@ public class AudioClient {
AudioPlayer player = new AudioPlayer();
AudioPlayer.FORMAT = AudioPlayer.defaultFormat(SAMPLE_RATE);
AudioPlayer.addLines(Shapes.generatePolygon(100, 0.5, 60));
AudioPlayer.addLines(Shapes.generatePolygram(5, 3, 0.5, 60));
AudioPlayer.addShapes(Shapes.generatePolygon(100, 0.5, 60));
AudioPlayer.addShapes(Shapes.generatePolygram(5, 3, 0.5, 60));
AudioPlayer.addShape(new Ellipse(0.5, 0.5));
AudioPlayer.setRotateSpeed(0.8);
AudioPlayer.setRotateSpeed(-0.8);
AudioPlayer.setTranslation(4, new Vector(1, 1));
AudioPlayer.setScale(0.5);

Wyświetl plik

@ -1,21 +1,23 @@
package audio;
import com.xtaudio.xt.*;
import shapes.Ellipse;
import shapes.Line;
import shapes.Shape;
import shapes.Vector;
import java.util.ArrayList;
import java.util.List;
public class AudioPlayer extends Thread {
public static XtFormat FORMAT;
private static volatile boolean stopped = false;
private static List<Line> lines = new ArrayList<>();
private static int currentLine = 0;
private static List<Shape> shapes = new ArrayList<>();
private static int currentShape = 0;
private static int framesDrawn = 0;
private static double[] phases = new double[2];
public static XtFormat FORMAT;
private static double TRANSLATE_SPEED = 0;
private static Vector TRANSLATE_VECTOR;
private static final int TRANSLATE_PHASE_INDEX = 0;
@ -28,81 +30,77 @@ public class AudioPlayer extends Thread {
XtFormat format = stream.getFormat();
for (int f = 0; f < frames; f++) {
Line line = currentLine();
Shape shape = currentShape();
line = scale(line);
line = rotate(line, stream.getFormat().mix.rate);
line = translate(line, stream.getFormat().mix.rate);
shape = scale(shape);
shape = rotate(shape, stream.getFormat().mix.rate);
shape = translate(shape, stream.getFormat().mix.rate);
int framesToDraw = (int) (line.length * line.getWeight());
double framesToDraw = shape.getLength() * shape.getWeight();
double drawingProgress = framesDrawn / framesToDraw;
for (int c = 0; c < format.outputs; c++) {
((float[]) output)[f * format.outputs] = nextX(line, framesToDraw);
((float[]) output)[f * format.outputs + 1] = nextY(line, framesToDraw);
((float[]) output)[f * format.outputs] = shape.nextX(drawingProgress);
((float[]) output)[f * format.outputs + 1] = shape.nextY(drawingProgress);
}
framesDrawn++;
if (framesDrawn > framesToDraw) {
framesDrawn = 0;
currentLine++;
currentShape++;
}
}
}
static float nextTheta(double sampleRate, double frequency, int phaseIndex) {
static double nextTheta(double sampleRate, double frequency, int phaseIndex) {
phases[phaseIndex] += frequency / sampleRate;
if (phases[phaseIndex] >= 1.0)
if (phases[phaseIndex] >= 1.0) {
phases[phaseIndex] = -1.0;
return (float) (phases[phaseIndex] * Math.PI);
}
private static float nextX(Line line, double framesToDraw) {
return (float) (line.getX1() + (line.getX2() - line.getX1()) * framesDrawn / framesToDraw);
}
private static float nextY(Line line, double framesToDraw) {
return (float) (line.getY1() + (line.getY2() - line.getY1()) * framesDrawn / framesToDraw);
}
private static Line scale(Line line) {
if (SCALE != 1) {
return line.scale(SCALE);
}
return line;
return phases[phaseIndex] * Math.PI;
}
private static Line rotate(Line line, double sampleRate) {
private static Shape scale(Shape shape) {
if (SCALE != 1) {
return shape.scale(SCALE);
}
return shape;
}
private static Shape rotate(Shape shape, double sampleRate) {
if (ROTATE_SPEED != 0) {
line = line.rotate(
shape = shape.rotate(
nextTheta(sampleRate, ROTATE_SPEED, TRANSLATE_PHASE_INDEX)
);
}
return line;
return shape;
}
private static Line translate(Line line, double sampleRate) {
private static Shape translate(Shape shape, double sampleRate) {
if (TRANSLATE_SPEED != 0 && !TRANSLATE_VECTOR.equals(new Vector())) {
return line.translate(TRANSLATE_VECTOR.scale(
return shape.translate(TRANSLATE_VECTOR.scale(
Math.sin(nextTheta(sampleRate, TRANSLATE_SPEED, ROTATE_PHASE_INDEX))
));
}
return line;
return shape;
}
public static void addLine(Line line) {
AudioPlayer.lines.add(line);
public static void addShape(Shape shape) {
AudioPlayer.shapes.add(shape);
}
public static void addLines(List<Line> lines) {
AudioPlayer.lines.addAll(lines);
public static void addShapes(List<Shape> shapes) {
AudioPlayer.shapes.addAll(shapes);
}
private static Line currentLine() {
return lines.get(currentLine % lines.size());
private static Shape currentShape() {
return shapes.get(currentShape % shapes.size());
}
public static void setRotateSpeed(double speed) {

Wyświetl plik

@ -27,8 +27,8 @@ public class Graph {
Node nodeA = nodes.get(line.getA());
Node nodeB = nodes.get(line.getB());
nodeA.addAdjacent(nodeB, line.length);
nodeB.addAdjacent(nodeA, line.length);
nodeA.addAdjacent(nodeB, line.getLength());
nodeB.addAdjacent(nodeA, line.getLength());
}
}
}

Wyświetl plik

@ -0,0 +1,57 @@
package shapes;
public class Ellipse implements Shape {
private final double a;
private final double b;
private final double weight;
private final double length;
public Ellipse(double a, double b, double weight) {
this.a = a;
this.b = b;
this.weight = weight;
// Approximation of length.
this.length = 2 * Math.PI * Math.sqrt((this.a * this.a + this.b * this.b) / 2);
}
public Ellipse(double a, double b) {
this(a, b, 100);
}
@Override
public float nextX(double drawingProgress) {
return (float) (a * Math.sin(2 * Math.PI * drawingProgress));
}
@Override
public float nextY(double drawingProgress) {
return (float) (b * Math.cos(2 * Math.PI * drawingProgress));
}
// TODO: Implement ellipse rotation.
@Override
public Shape rotate(double theta) {
return this;
}
@Override
public Shape scale(double factor) {
return new Ellipse(a * factor, b * factor, weight);
}
// TODO: Implement ellipse translation.
@Override
public Shape translate(Vector vector) {
return this;
}
@Override
public double getWeight() {
return weight;
}
@Override
public double getLength() {
return length;
}
}

Wyświetl plik

@ -1,12 +1,12 @@
package shapes;
public class Line {
public class Line implements Shape {
private final Vector a;
private final Vector b;
private final double weight;
// Storing the length to save on repeat calculations.
public final double length;
private final double length;
public static final double DEFAULT_WEIGHT = 100;
@ -33,14 +33,17 @@ public class Line {
return Math.sqrt(Math.pow(getX1() - getX2(), 2) + Math.pow(getY1() - getY2(), 2));
}
@Override
public Line rotate(double theta) {
return new Line(getA().rotate(theta), getB().rotate(theta), getWeight());
}
@Override
public Line translate(Vector vector) {
return new Line(getA().add(vector), getB().add(vector));
}
@Override
public Line scale(double factor) {
return new Line(getA().scale(factor), getB().scale(factor));
}
@ -49,6 +52,16 @@ public class Line {
return new Line(getA().copy(), getB().copy(), getWeight());
}
@Override
public float nextX(double drawingProgress) {
return (float) (getX1() + (getX2() - getX1()) * drawingProgress);
}
@Override
public float nextY(double drawingProgress) {
return (float) (getY1() + (getY2() - getY1()) * drawingProgress);
}
public Vector getA() {
return a;
}
@ -89,10 +102,16 @@ public class Line {
return new Line(getX1(), getY1(), getX2(), y2);
}
@Override
public double getWeight() {
return weight;
}
@Override
public double getLength() {
return length;
}
public Line setWeight(double weight) {
return new Line(getX1(), getY1(), getX2(), getY2(), weight);
}

Wyświetl plik

@ -0,0 +1,11 @@
package shapes;
public interface Shape {
float nextX(double drawingProgress);
float nextY(double drawingProgress);
Shape rotate(double theta);
Shape scale(double factor);
Shape translate(Vector vector);
double getWeight();
double getLength();
}

Wyświetl plik

@ -4,8 +4,8 @@ import java.util.ArrayList;
import java.util.List;
public class Shapes {
public static List<Line> generatePolygram(int sides, int angleJump, Vector start, double weight) {
List<Line> polygon = new ArrayList<>();
public static List<Shape> generatePolygram(int sides, int angleJump, Vector start, double weight) {
List<Shape> polygon = new ArrayList<>();
double theta = angleJump * 2 * Math.PI / sides;
@ -22,31 +22,31 @@ public class Shapes {
return polygon;
}
public static List<Line> generatePolygram(int sides, int angleJump, Vector start) {
public static List<Shape> generatePolygram(int sides, int angleJump, Vector start) {
return generatePolygram(sides, angleJump, start, Line.DEFAULT_WEIGHT);
}
public static List<Line> generatePolygram(int sides, int angleJump, double scale, double weight) {
public static List<Shape> generatePolygram(int sides, int angleJump, double scale, double weight) {
return generatePolygram(sides, angleJump, new Vector(scale, scale), weight);
}
public static List<Line> generatePolygram(int sides, int angleJump, double scale) {
public static List<Shape> generatePolygram(int sides, int angleJump, double scale) {
return generatePolygram(sides, angleJump, new Vector(scale, scale));
}
public static List<Line> generatePolygon(int sides, Vector start, double weight) {
public static List<Shape> generatePolygon(int sides, Vector start, double weight) {
return generatePolygram(sides, 1, start, weight);
}
public static List<Line> generatePolygon(int sides, Vector start) {
public static List<Shape> generatePolygon(int sides, Vector start) {
return generatePolygram(sides, 1, start);
}
public static List<Line> generatePolygon(int sides, double scale, double weight) {
public static List<Shape> generatePolygon(int sides, double scale, double weight) {
return generatePolygon(sides, new Vector(scale, scale), weight);
}
public static List<Line> generatePolygon(int sides, double scale) {
public static List<Shape> generatePolygon(int sides, double scale) {
return generatePolygon(sides, new Vector(scale, scale));
}