kopia lustrzana https://github.com/jameshball/osci-render
Added shape interface to clean up code and added ellipse class
rodzic
45b66fa4a5
commit
2b6f2932c7
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue