kopia lustrzana https://github.com/jameshball/osci-render
Improve stability with js oscilloscope
rodzic
7a778112ee
commit
ade45fa9e6
10
pom.xml
10
pom.xml
|
@ -181,6 +181,16 @@
|
||||||
<artifactId>Java-WebSocket</artifactId>
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
<version>1.5.3</version>
|
<version>1.5.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.7.36</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>1.7.36</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class Gui extends Application {
|
||||||
stage.show();
|
stage.show();
|
||||||
|
|
||||||
stage.setOnCloseRequest(t -> {
|
stage.setOnCloseRequest(t -> {
|
||||||
|
controller.shutdown();
|
||||||
Platform.exit();
|
Platform.exit();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,7 +51,7 @@ import sh.ball.audio.midi.MidiNote;
|
||||||
import sh.ball.engine.ObjectServer;
|
import sh.ball.engine.ObjectServer;
|
||||||
import sh.ball.engine.ObjectSet;
|
import sh.ball.engine.ObjectSet;
|
||||||
import sh.ball.gui.Gui;
|
import sh.ball.gui.Gui;
|
||||||
import sh.ball.oscilloscope.OscilloscopeServer;
|
import sh.ball.oscilloscope.ByteWebSocketServer;
|
||||||
import sh.ball.parser.obj.ObjFrameSettings;
|
import sh.ball.parser.obj.ObjFrameSettings;
|
||||||
import sh.ball.parser.obj.ObjParser;
|
import sh.ball.parser.obj.ObjParser;
|
||||||
import sh.ball.parser.ParserFactory;
|
import sh.ball.parser.ParserFactory;
|
||||||
|
@ -73,7 +73,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
||||||
private String openProjectPath;
|
private String openProjectPath;
|
||||||
private final FileChooser wavFileChooser = new FileChooser();
|
private final FileChooser wavFileChooser = new FileChooser();
|
||||||
|
|
||||||
private ObjectServer server;
|
private ObjectServer objectServer;
|
||||||
|
|
||||||
// audio
|
// audio
|
||||||
private int sampleRate;
|
private int sampleRate;
|
||||||
|
@ -106,6 +106,13 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
||||||
private final FileChooser osciFileChooser = new FileChooser();
|
private final FileChooser osciFileChooser = new FileChooser();
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
|
|
||||||
|
// software oscilloscope
|
||||||
|
private static final int SOSCI_NUM_VERTICES = 4096;
|
||||||
|
private static final int SOSCI_VERTEX_SIZE = 2;
|
||||||
|
private static final int FRAME_SIZE = 2;
|
||||||
|
private byte[] buffer;
|
||||||
|
private ByteWebSocketServer webSocketServer;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private EffectsController effectsController;
|
private EffectsController effectsController;
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -206,6 +213,10 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
||||||
channelClosestToZero.put(slider, closestToZero);
|
channelClosestToZero.put(slider, closestToZero);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
webSocketServer.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
// alternates between recording and not recording when called.
|
// alternates between recording and not recording when called.
|
||||||
// If it is a non-timed recording, it is saved when this is called and
|
// If it is a non-timed recording, it is saved when this is called and
|
||||||
// recording is stopped. If it is a time recording, this function will cancel
|
// recording is stopped. If it is a time recording, this function will cancel
|
||||||
|
@ -457,15 +468,30 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server = new ObjectServer(this::enableObjectServerRendering, this::disableObjectServerRendering);
|
objectServer = new ObjectServer(this::enableObjectServerRendering, this::disableObjectServerRendering);
|
||||||
new Thread(server).start();
|
new Thread(objectServer).start();
|
||||||
new OscilloscopeServer<>(audioPlayer, 2).start();
|
|
||||||
|
webSocketServer = new ByteWebSocketServer();
|
||||||
|
webSocketServer.start();
|
||||||
|
this.buffer = new byte[FRAME_SIZE * SOSCI_NUM_VERTICES * SOSCI_VERTEX_SIZE];
|
||||||
|
new Thread(() -> sendAudioDataToWebSocket(webSocketServer)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendAudioDataToWebSocket(ByteWebSocketServer server) {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
audioPlayer.read(buffer);
|
||||||
|
server.send(buffer);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableObjectServerRendering() {
|
private void enableObjectServerRendering() {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
objectServerRendering = true;
|
objectServerRendering = true;
|
||||||
ObjectSet set = server.getObjectSet();
|
ObjectSet set = objectServer.getObjectSet();
|
||||||
frameSources.forEach(FrameSource::disable);
|
frameSources.forEach(FrameSource::disable);
|
||||||
set.enable();
|
set.enable();
|
||||||
|
|
||||||
|
@ -483,7 +509,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
||||||
|
|
||||||
private void disableObjectServerRendering() {
|
private void disableObjectServerRendering() {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
server.getObjectSet().disable();
|
objectServer.getObjectSet().disable();
|
||||||
objectServerRendering = false;
|
objectServerRendering = false;
|
||||||
changeFrameSource(currentFrameSource);
|
changeFrameSource(currentFrameSource);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package sh.ball.oscilloscope;
|
||||||
|
|
||||||
|
import org.java_websocket.WebSocket;
|
||||||
|
import org.java_websocket.handshake.ClientHandshake;
|
||||||
|
import org.java_websocket.server.WebSocketServer;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ByteWebSocketServer extends WebSocketServer {
|
||||||
|
|
||||||
|
private static final int TCP_PORT = 42988;
|
||||||
|
|
||||||
|
private final Set<WebSocket> conns;
|
||||||
|
|
||||||
|
public ByteWebSocketServer() {
|
||||||
|
super(new InetSocketAddress(TCP_PORT));
|
||||||
|
this.conns = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void send(byte[] bytes) {
|
||||||
|
for (WebSocket sock : conns) {
|
||||||
|
sock.send(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void onOpen(WebSocket conn, ClientHandshake handshake) {
|
||||||
|
conns.add(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void onClose(WebSocket conn, int code, String reason, boolean remote) {
|
||||||
|
conns.remove(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void onMessage(WebSocket conn, String message) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void onError(WebSocket conn, Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
if (conn != null) {
|
||||||
|
conns.remove(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void shutdown() {
|
||||||
|
conns.forEach(WebSocket::close);
|
||||||
|
conns.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {}
|
||||||
|
}
|
|
@ -1,83 +0,0 @@
|
||||||
package sh.ball.oscilloscope;
|
|
||||||
|
|
||||||
import org.java_websocket.WebSocket;
|
|
||||||
import org.java_websocket.handshake.ClientHandshake;
|
|
||||||
import org.java_websocket.server.WebSocketServer;
|
|
||||||
import sh.ball.audio.AudioPlayer;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.ShortBuffer;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class OscilloscopeServer<S> extends WebSocketServer {
|
|
||||||
|
|
||||||
private static final int TCP_PORT = 4444;
|
|
||||||
private static final int NUM_VERTICES = 2048;
|
|
||||||
private static final int VERTEX_SIZE = 2;
|
|
||||||
|
|
||||||
private final Set<WebSocket> conns;
|
|
||||||
private final AudioPlayer<S> audioPlayer;
|
|
||||||
private final int frameSize;
|
|
||||||
private final byte[] buffer;
|
|
||||||
|
|
||||||
public OscilloscopeServer(AudioPlayer<S> audioPlayer, int frameSize) {
|
|
||||||
super(new InetSocketAddress(TCP_PORT));
|
|
||||||
this.conns = new HashSet<>();
|
|
||||||
this.audioPlayer = audioPlayer;
|
|
||||||
this.frameSize = frameSize;
|
|
||||||
this.buffer = new byte[frameSize * NUM_VERTICES * VERTEX_SIZE];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void send(byte[] bytes) {
|
|
||||||
for (WebSocket sock : conns) {
|
|
||||||
sock.send(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onOpen(WebSocket conn, ClientHandshake handshake) {
|
|
||||||
conns.add(conn);
|
|
||||||
System.out.println("New connection from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
|
|
||||||
conns.remove(conn);
|
|
||||||
System.out.println("Closed connection to " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(WebSocket conn, String message) {
|
|
||||||
System.out.println("Message from client: " + message);
|
|
||||||
for (WebSocket sock : conns) {
|
|
||||||
sock.send(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(WebSocket conn, Exception ex) {
|
|
||||||
//ex.printStackTrace();
|
|
||||||
if (conn != null) {
|
|
||||||
conns.remove(conn);
|
|
||||||
// do some thing if required
|
|
||||||
}
|
|
||||||
System.out.println("ERROR from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStart() {
|
|
||||||
new Thread(() -> {
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
audioPlayer.read(buffer);
|
|
||||||
send(buffer);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
|
Ładowanie…
Reference in New Issue