kopia lustrzana https://github.com/jameshball/osci-render
Rename Renderer to AudioPlayer
rodzic
45289200a4
commit
77ede06cf4
|
@ -2,244 +2,23 @@ package sh.ball.audio;
|
|||
|
||||
import sh.ball.audio.effect.Effect;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
public interface AudioPlayer<S, T> extends Runnable {
|
||||
|
||||
import sh.ball.audio.engine.AudioEngine;
|
||||
import sh.ball.shapes.Shape;
|
||||
import sh.ball.shapes.Vector2;
|
||||
void stop();
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
void setQuality(double quality);
|
||||
|
||||
public class AudioPlayer implements Renderer<List<Shape>, AudioInputStream> {
|
||||
void addFrame(S frame);
|
||||
|
||||
// Arbitrary max count for effects
|
||||
private static final int MAX_COUNT = 10000;
|
||||
private static final int BUFFER_SIZE = 5;
|
||||
// Is this always true? Might need to check from AudioEngine
|
||||
private static final int BITS_PER_SAMPLE = 16;
|
||||
private static final boolean SIGNED = true;
|
||||
private static final boolean BIG_ENDIAN = false;
|
||||
// Stereo audio
|
||||
private static final int NUM_OUTPUTS = 2;
|
||||
void addEffect(Object identifier, Effect effect);
|
||||
|
||||
private final AudioEngine audioEngine;
|
||||
private final BlockingQueue<List<Shape>> frameQueue = new ArrayBlockingQueue<>(BUFFER_SIZE);
|
||||
private final Map<Object, Effect> effects = new HashMap<>();
|
||||
private final ReentrantLock renderLock = new ReentrantLock();
|
||||
private final List<Listener> listeners = new ArrayList<>();
|
||||
void removeEffect(Object identifier);
|
||||
|
||||
private ByteArrayOutputStream outputStream;
|
||||
private boolean recording = false;
|
||||
private int framesRecorded = 0;
|
||||
private List<Shape> frame;
|
||||
private int currentShape = 0;
|
||||
private int audioFramesDrawn = 0;
|
||||
private int count = 0;
|
||||
void read(byte[] buffer) throws InterruptedException;
|
||||
|
||||
private double weight = Shape.DEFAULT_WEIGHT;
|
||||
void startRecord();
|
||||
|
||||
public AudioPlayer(AudioEngine audioEngine) {
|
||||
this.audioEngine = audioEngine;
|
||||
}
|
||||
int samplesPerSecond();
|
||||
|
||||
private Vector2 generateChannels() throws InterruptedException {
|
||||
Shape shape = getCurrentShape().setWeight(weight);
|
||||
|
||||
double totalAudioFrames = shape.getWeight() * shape.getLength();
|
||||
double drawingProgress = totalAudioFrames == 0 ? 1 : audioFramesDrawn / totalAudioFrames;
|
||||
Vector2 nextVector = applyEffects(count, shape.nextVector(drawingProgress));
|
||||
|
||||
Vector2 channels = cutoff(nextVector);
|
||||
writeChannels((float) channels.getX(), (float) channels.getY());
|
||||
|
||||
audioFramesDrawn++;
|
||||
|
||||
if (++count > MAX_COUNT) {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
if (audioFramesDrawn > totalAudioFrames) {
|
||||
audioFramesDrawn = 0;
|
||||
currentShape++;
|
||||
}
|
||||
|
||||
if (currentShape >= frame.size()) {
|
||||
currentShape = 0;
|
||||
frame = frameQueue.take();
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
private void writeChannels(float leftChannel, float rightChannel) {
|
||||
int left = (int)(leftChannel * Short.MAX_VALUE);
|
||||
int right = (int)(rightChannel * Short.MAX_VALUE);
|
||||
|
||||
byte b0 = (byte) left;
|
||||
byte b1 = (byte)(left >> 8);
|
||||
byte b2 = (byte) right;
|
||||
byte b3 = (byte)(right >> 8);
|
||||
|
||||
if (recording) {
|
||||
outputStream.write(b0);
|
||||
outputStream.write(b1);
|
||||
outputStream.write(b2);
|
||||
outputStream.write(b3);
|
||||
}
|
||||
|
||||
for (Listener listener : listeners) {
|
||||
listener.write(b0);
|
||||
listener.write(b1);
|
||||
listener.write(b2);
|
||||
listener.write(b3);
|
||||
listener.notifyIfFull();
|
||||
}
|
||||
|
||||
framesRecorded++;
|
||||
}
|
||||
|
||||
private Vector2 cutoff(Vector2 vector) {
|
||||
if (vector.getX() < -1) {
|
||||
vector = vector.setX(-1);
|
||||
} else if (vector.getX() > 1) {
|
||||
vector = vector.setX(1);
|
||||
}
|
||||
if (vector.getY() < -1) {
|
||||
vector = vector.setY(-1);
|
||||
} else if (vector.getY() > 1) {
|
||||
vector = vector.setY(1);
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
||||
private Vector2 applyEffects(int frame, Vector2 vector) {
|
||||
for (Effect effect : effects.values()) {
|
||||
vector = effect.apply(frame, vector);
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuality(double quality) {
|
||||
this.weight = quality;
|
||||
}
|
||||
|
||||
private Shape getCurrentShape() {
|
||||
if (frame.size() == 0) {
|
||||
return new Vector2();
|
||||
}
|
||||
|
||||
return frame.get(currentShape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
frame = frameQueue.take();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Initial frame not found. Cannot continue.");
|
||||
}
|
||||
|
||||
audioEngine.play(this::generateChannels, renderLock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
audioEngine.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFrame(List<Shape> frame) {
|
||||
try {
|
||||
frameQueue.put(frame);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Frame missed.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEffect(Object identifier, Effect effect) {
|
||||
effects.put(identifier, effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEffect(Object identifier) {
|
||||
effects.remove(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(byte[] buffer) throws InterruptedException {
|
||||
Listener listener = new Listener(buffer);
|
||||
try {
|
||||
renderLock.lock();
|
||||
listeners.add(listener);
|
||||
} finally {
|
||||
renderLock.unlock();
|
||||
}
|
||||
listener.waitUntilFull();
|
||||
try {
|
||||
renderLock.lock();
|
||||
listeners.remove(listener);
|
||||
} finally {
|
||||
renderLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRecord() {
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
framesRecorded = 0;
|
||||
recording = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int samplesPerSecond() {
|
||||
return audioEngine.sampleRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioInputStream stopRecord() {
|
||||
recording = false;
|
||||
byte[] input = outputStream.toByteArray();
|
||||
outputStream = null;
|
||||
|
||||
AudioFormat audioFormat = new AudioFormat(audioEngine.sampleRate(), BITS_PER_SAMPLE, NUM_OUTPUTS, SIGNED, BIG_ENDIAN);
|
||||
|
||||
return new AudioInputStream(new ByteArrayInputStream(input), audioFormat, framesRecorded);
|
||||
}
|
||||
|
||||
private static class Listener {
|
||||
private final byte[] buffer;
|
||||
private final Semaphore sema;
|
||||
|
||||
private int offset;
|
||||
|
||||
private Listener(byte[] buffer) {
|
||||
this.buffer = buffer;
|
||||
this.sema = new Semaphore(0);
|
||||
}
|
||||
|
||||
private void waitUntilFull() throws InterruptedException {
|
||||
sema.acquire();
|
||||
}
|
||||
|
||||
private void notifyIfFull() {
|
||||
if (offset >= buffer.length) {
|
||||
sema.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void write(byte b) {
|
||||
if (offset < buffer.length) {
|
||||
buffer[offset++] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
T stopRecord();
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ package sh.ball.audio;
|
|||
|
||||
public class FrameProducer<S, T> implements Runnable {
|
||||
|
||||
private final Renderer<S, T> renderer;
|
||||
private final AudioPlayer<S, T> audioPlayer;
|
||||
private final FrameSet<S> frames;
|
||||
|
||||
private boolean running;
|
||||
|
||||
public FrameProducer(Renderer<S, T> renderer, FrameSet<S> frames) {
|
||||
this.renderer = renderer;
|
||||
public FrameProducer(AudioPlayer<S, T> audioPlayer, FrameSet<S> frames) {
|
||||
this.audioPlayer = audioPlayer;
|
||||
this.frames = frames;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ public class FrameProducer<S, T> implements Runnable {
|
|||
public void run() {
|
||||
running = true;
|
||||
while (running) {
|
||||
renderer.addFrame(frames.next());
|
||||
audioPlayer.addFrame(frames.next());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,14 +12,14 @@ public class FrequencyAnalyser<S, T> implements Runnable {
|
|||
// increase this for higher frequency resolution, but less frequent frequency calculation
|
||||
private static final int DEFAULT_POWER_OF_TWO = 18;
|
||||
|
||||
private final Renderer<S, T> renderer;
|
||||
private final AudioPlayer<S, T> audioPlayer;
|
||||
private final List<FrequencyListener> listeners = new ArrayList<>();
|
||||
private final int frameSize;
|
||||
private final int sampleRate;
|
||||
private final int powerOfTwo;
|
||||
|
||||
public FrequencyAnalyser(Renderer<S, T> renderer, int frameSize, int sampleRate) {
|
||||
this.renderer = renderer;
|
||||
public FrequencyAnalyser(AudioPlayer<S, T> audioPlayer, int frameSize, int sampleRate) {
|
||||
this.audioPlayer = audioPlayer;
|
||||
this.frameSize = frameSize;
|
||||
this.sampleRate = sampleRate;
|
||||
this.powerOfTwo = (int) (DEFAULT_POWER_OF_TWO - Math.log(DEFAULT_SAMPLE_RATE / sampleRate) / Math.log(2));
|
||||
|
@ -42,7 +42,7 @@ public class FrequencyAnalyser<S, T> implements Runnable {
|
|||
|
||||
while (true) {
|
||||
try {
|
||||
renderer.read(buf);
|
||||
audioPlayer.read(buf);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
import sh.ball.audio.effect.Effect;
|
||||
|
||||
public interface Renderer<S, T> extends Runnable {
|
||||
|
||||
void stop();
|
||||
|
||||
void setQuality(double quality);
|
||||
|
||||
void addFrame(S frame);
|
||||
|
||||
void addEffect(Object identifier, Effect effect);
|
||||
|
||||
void removeEffect(Object identifier);
|
||||
|
||||
void read(byte[] buffer) throws InterruptedException;
|
||||
|
||||
void startRecord();
|
||||
|
||||
int samplesPerSecond();
|
||||
|
||||
T stopRecord();
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
package sh.ball.audio;
|
||||
|
||||
import sh.ball.audio.effect.Effect;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
import sh.ball.audio.engine.AudioEngine;
|
||||
import sh.ball.shapes.Shape;
|
||||
import sh.ball.shapes.Vector2;
|
||||
|
||||
import javax.sound.sampled.AudioFormat;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ShapeAudioPlayer implements AudioPlayer<List<Shape>, AudioInputStream> {
|
||||
|
||||
// Arbitrary max count for effects
|
||||
private static final int MAX_COUNT = 10000;
|
||||
private static final int BUFFER_SIZE = 5;
|
||||
// Is this always true? Might need to check from AudioEngine
|
||||
private static final int BITS_PER_SAMPLE = 16;
|
||||
private static final boolean SIGNED = true;
|
||||
private static final boolean BIG_ENDIAN = false;
|
||||
// Stereo audio
|
||||
private static final int NUM_OUTPUTS = 2;
|
||||
|
||||
private final AudioEngine audioEngine;
|
||||
private final BlockingQueue<List<Shape>> frameQueue = new ArrayBlockingQueue<>(BUFFER_SIZE);
|
||||
private final Map<Object, Effect> effects = new HashMap<>();
|
||||
private final ReentrantLock renderLock = new ReentrantLock();
|
||||
private final List<Listener> listeners = new ArrayList<>();
|
||||
|
||||
private ByteArrayOutputStream outputStream;
|
||||
private boolean recording = false;
|
||||
private int framesRecorded = 0;
|
||||
private List<Shape> frame;
|
||||
private int currentShape = 0;
|
||||
private int audioFramesDrawn = 0;
|
||||
private int count = 0;
|
||||
|
||||
private double weight = Shape.DEFAULT_WEIGHT;
|
||||
|
||||
public ShapeAudioPlayer(AudioEngine audioEngine) {
|
||||
this.audioEngine = audioEngine;
|
||||
}
|
||||
|
||||
private Vector2 generateChannels() throws InterruptedException {
|
||||
Shape shape = getCurrentShape().setWeight(weight);
|
||||
|
||||
double totalAudioFrames = shape.getWeight() * shape.getLength();
|
||||
double drawingProgress = totalAudioFrames == 0 ? 1 : audioFramesDrawn / totalAudioFrames;
|
||||
Vector2 nextVector = applyEffects(count, shape.nextVector(drawingProgress));
|
||||
|
||||
Vector2 channels = cutoff(nextVector);
|
||||
writeChannels((float) channels.getX(), (float) channels.getY());
|
||||
|
||||
audioFramesDrawn++;
|
||||
|
||||
if (++count > MAX_COUNT) {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
if (audioFramesDrawn > totalAudioFrames) {
|
||||
audioFramesDrawn = 0;
|
||||
currentShape++;
|
||||
}
|
||||
|
||||
if (currentShape >= frame.size()) {
|
||||
currentShape = 0;
|
||||
frame = frameQueue.take();
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
private void writeChannels(float leftChannel, float rightChannel) {
|
||||
int left = (int)(leftChannel * Short.MAX_VALUE);
|
||||
int right = (int)(rightChannel * Short.MAX_VALUE);
|
||||
|
||||
byte b0 = (byte) left;
|
||||
byte b1 = (byte)(left >> 8);
|
||||
byte b2 = (byte) right;
|
||||
byte b3 = (byte)(right >> 8);
|
||||
|
||||
if (recording) {
|
||||
outputStream.write(b0);
|
||||
outputStream.write(b1);
|
||||
outputStream.write(b2);
|
||||
outputStream.write(b3);
|
||||
}
|
||||
|
||||
for (Listener listener : listeners) {
|
||||
listener.write(b0);
|
||||
listener.write(b1);
|
||||
listener.write(b2);
|
||||
listener.write(b3);
|
||||
listener.notifyIfFull();
|
||||
}
|
||||
|
||||
framesRecorded++;
|
||||
}
|
||||
|
||||
private Vector2 cutoff(Vector2 vector) {
|
||||
if (vector.getX() < -1) {
|
||||
vector = vector.setX(-1);
|
||||
} else if (vector.getX() > 1) {
|
||||
vector = vector.setX(1);
|
||||
}
|
||||
if (vector.getY() < -1) {
|
||||
vector = vector.setY(-1);
|
||||
} else if (vector.getY() > 1) {
|
||||
vector = vector.setY(1);
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
||||
private Vector2 applyEffects(int frame, Vector2 vector) {
|
||||
for (Effect effect : effects.values()) {
|
||||
vector = effect.apply(frame, vector);
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuality(double quality) {
|
||||
this.weight = quality;
|
||||
}
|
||||
|
||||
private Shape getCurrentShape() {
|
||||
if (frame.size() == 0) {
|
||||
return new Vector2();
|
||||
}
|
||||
|
||||
return frame.get(currentShape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
frame = frameQueue.take();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Initial frame not found. Cannot continue.");
|
||||
}
|
||||
|
||||
audioEngine.play(this::generateChannels, renderLock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
audioEngine.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFrame(List<Shape> frame) {
|
||||
try {
|
||||
frameQueue.put(frame);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Frame missed.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEffect(Object identifier, Effect effect) {
|
||||
effects.put(identifier, effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeEffect(Object identifier) {
|
||||
effects.remove(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(byte[] buffer) throws InterruptedException {
|
||||
Listener listener = new Listener(buffer);
|
||||
try {
|
||||
renderLock.lock();
|
||||
listeners.add(listener);
|
||||
} finally {
|
||||
renderLock.unlock();
|
||||
}
|
||||
listener.waitUntilFull();
|
||||
try {
|
||||
renderLock.lock();
|
||||
listeners.remove(listener);
|
||||
} finally {
|
||||
renderLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRecord() {
|
||||
outputStream = new ByteArrayOutputStream();
|
||||
framesRecorded = 0;
|
||||
recording = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int samplesPerSecond() {
|
||||
return audioEngine.sampleRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AudioInputStream stopRecord() {
|
||||
recording = false;
|
||||
byte[] input = outputStream.toByteArray();
|
||||
outputStream = null;
|
||||
|
||||
AudioFormat audioFormat = new AudioFormat(audioEngine.sampleRate(), BITS_PER_SAMPLE, NUM_OUTPUTS, SIGNED, BIG_ENDIAN);
|
||||
|
||||
return new AudioInputStream(new ByteArrayInputStream(input), audioFormat, framesRecorded);
|
||||
}
|
||||
|
||||
private static class Listener {
|
||||
private final byte[] buffer;
|
||||
private final Semaphore sema;
|
||||
|
||||
private int offset;
|
||||
|
||||
private Listener(byte[] buffer) {
|
||||
this.buffer = buffer;
|
||||
this.sema = new Semaphore(0);
|
||||
}
|
||||
|
||||
private void waitUntilFull() throws InterruptedException {
|
||||
sema.acquire();
|
||||
}
|
||||
|
||||
private void notifyIfFull() {
|
||||
if (offset >= buffer.length) {
|
||||
sema.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void write(byte b) {
|
||||
if (offset < buffer.length) {
|
||||
buffer[offset++] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ public class Controller implements Initializable, FrequencyListener, Listener {
|
|||
private static final InputStream DEFAULT_OBJ = Controller.class.getResourceAsStream("/models/cube.obj");
|
||||
|
||||
private final FileChooser fileChooser = new FileChooser();
|
||||
private final Renderer<List<Shape>, AudioInputStream> renderer;
|
||||
private final AudioPlayer<List<Shape>, AudioInputStream> audioPlayer;
|
||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private final int sampleRate;
|
||||
|
@ -121,12 +121,12 @@ public class Controller implements Initializable, FrequencyListener, Listener {
|
|||
@FXML
|
||||
private Slider wobbleSlider;
|
||||
|
||||
public Controller(Renderer<List<Shape>, AudioInputStream> renderer) throws IOException {
|
||||
this.renderer = renderer;
|
||||
public Controller(AudioPlayer<List<Shape>, AudioInputStream> audioPlayer) throws IOException {
|
||||
this.audioPlayer = audioPlayer;
|
||||
FrameSet<List<Shape>> frames = new ObjParser(DEFAULT_OBJ).parse();
|
||||
frames.addListener(this);
|
||||
this.producer = new FrameProducer<>(renderer, frames);
|
||||
this.sampleRate = renderer.samplesPerSecond();
|
||||
this.producer = new FrameProducer<>(audioPlayer, frames);
|
||||
this.sampleRate = audioPlayer.samplesPerSecond();
|
||||
this.rotateEffect = new RotateEffect(sampleRate);
|
||||
this.translateEffect = new TranslateEffect(sampleRate);
|
||||
this.wobbleEffect = new WobbleEffect(sampleRate);
|
||||
|
@ -136,7 +136,7 @@ public class Controller implements Initializable, FrequencyListener, Listener {
|
|||
private Map<Slider, Consumer<Double>> initializeSliderMap() {
|
||||
return Map.of(
|
||||
weightSlider,
|
||||
renderer::setQuality,
|
||||
audioPlayer::setQuality,
|
||||
rotateSpeedSlider,
|
||||
rotateEffect::setSpeed,
|
||||
translationSpeedSlider,
|
||||
|
@ -238,15 +238,15 @@ public class Controller implements Initializable, FrequencyListener, Listener {
|
|||
|
||||
updateObjectRotateSpeed();
|
||||
|
||||
renderer.addEffect(EffectType.SCALE, scaleEffect);
|
||||
renderer.addEffect(EffectType.ROTATE, rotateEffect);
|
||||
renderer.addEffect(EffectType.TRANSLATE, translateEffect);
|
||||
audioPlayer.addEffect(EffectType.SCALE, scaleEffect);
|
||||
audioPlayer.addEffect(EffectType.ROTATE, rotateEffect);
|
||||
audioPlayer.addEffect(EffectType.TRANSLATE, translateEffect);
|
||||
|
||||
executor.submit(producer);
|
||||
Thread renderThread = new Thread(renderer);
|
||||
Thread renderThread = new Thread(audioPlayer);
|
||||
renderThread.setUncaughtExceptionHandler((thread, throwable) -> throwable.printStackTrace());
|
||||
renderThread.start();
|
||||
FrequencyAnalyser<List<Shape>, AudioInputStream> analyser = new FrequencyAnalyser<>(renderer, 2, sampleRate);
|
||||
FrequencyAnalyser<List<Shape>, AudioInputStream> analyser = new FrequencyAnalyser<>(audioPlayer, 2, sampleRate);
|
||||
analyser.addListener(this);
|
||||
analyser.addListener(wobbleEffect);
|
||||
new Thread(analyser).start();
|
||||
|
@ -257,10 +257,10 @@ public class Controller implements Initializable, FrequencyListener, Listener {
|
|||
if (recording) {
|
||||
recordLabel.setText("Recording...");
|
||||
recordButton.setText("Stop Recording");
|
||||
renderer.startRecord();
|
||||
audioPlayer.startRecord();
|
||||
} else {
|
||||
recordButton.setText("Record");
|
||||
AudioInputStream input = renderer.stopRecord();
|
||||
AudioInputStream input = audioPlayer.stopRecord();
|
||||
try {
|
||||
File file = fileChooser.showSaveDialog(stage);
|
||||
SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
|
||||
|
@ -315,10 +315,10 @@ public class Controller implements Initializable, FrequencyListener, Listener {
|
|||
|
||||
private void updateEffect(EffectType type, boolean checked, Effect effect) {
|
||||
if (checked) {
|
||||
renderer.addEffect(type, effect);
|
||||
audioPlayer.addEffect(type, effect);
|
||||
effectTypes.get(type).setDisable(false);
|
||||
} else {
|
||||
renderer.removeEffect(type);
|
||||
audioPlayer.removeEffect(type);
|
||||
effectTypes.get(type).setDisable(true);
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ public class Controller implements Initializable, FrequencyListener, Listener {
|
|||
String path = file.getAbsolutePath();
|
||||
FrameSet<List<Shape>> frames = ParserFactory.getParser(path).parse();
|
||||
frames.addListener(this);
|
||||
producer = new FrameProducer<>(renderer, frames);
|
||||
producer = new FrameProducer<>(audioPlayer, frames);
|
||||
|
||||
updateObjectRotateSpeed();
|
||||
updateFocalLength();
|
||||
|
|
|
@ -10,7 +10,7 @@ import javafx.scene.input.KeyCode;
|
|||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.stage.Stage;
|
||||
import sh.ball.audio.AudioPlayer;
|
||||
import sh.ball.audio.ShapeAudioPlayer;
|
||||
import sh.ball.audio.engine.XtAudioEngine;
|
||||
import sh.ball.engine.Vector3;
|
||||
|
||||
|
@ -24,7 +24,7 @@ public class Gui extends Application {
|
|||
System.setProperty("prism.lcdtext", "false");
|
||||
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/osci-render.fxml"));
|
||||
Controller controller = new Controller(new AudioPlayer(new XtAudioEngine()));
|
||||
Controller controller = new Controller(new ShapeAudioPlayer(new XtAudioEngine()));
|
||||
loader.setController(controller);
|
||||
Parent root = loader.load();
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue