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>
|
||||
<version>1.5.3</version>
|
||||
</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>
|
||||
<profiles>
|
||||
<profile>
|
||||
|
|
|
@ -90,6 +90,7 @@ public class Gui extends Application {
|
|||
stage.show();
|
||||
|
||||
stage.setOnCloseRequest(t -> {
|
||||
controller.shutdown();
|
||||
Platform.exit();
|
||||
System.exit(0);
|
||||
});
|
||||
|
|
|
@ -51,7 +51,7 @@ import sh.ball.audio.midi.MidiNote;
|
|||
import sh.ball.engine.ObjectServer;
|
||||
import sh.ball.engine.ObjectSet;
|
||||
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.ObjParser;
|
||||
import sh.ball.parser.ParserFactory;
|
||||
|
@ -73,7 +73,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
|||
private String openProjectPath;
|
||||
private final FileChooser wavFileChooser = new FileChooser();
|
||||
|
||||
private ObjectServer server;
|
||||
private ObjectServer objectServer;
|
||||
|
||||
// audio
|
||||
private int sampleRate;
|
||||
|
@ -106,6 +106,13 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
|||
private final FileChooser osciFileChooser = new FileChooser();
|
||||
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
|
||||
private EffectsController effectsController;
|
||||
@FXML
|
||||
|
@ -206,6 +213,10 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
|||
channelClosestToZero.put(slider, closestToZero);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
webSocketServer.shutdown();
|
||||
}
|
||||
|
||||
// alternates between recording and not recording when called.
|
||||
// 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
|
||||
|
@ -457,15 +468,30 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
|||
}
|
||||
}
|
||||
|
||||
server = new ObjectServer(this::enableObjectServerRendering, this::disableObjectServerRendering);
|
||||
new Thread(server).start();
|
||||
new OscilloscopeServer<>(audioPlayer, 2).start();
|
||||
objectServer = new ObjectServer(this::enableObjectServerRendering, this::disableObjectServerRendering);
|
||||
new Thread(objectServer).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() {
|
||||
Platform.runLater(() -> {
|
||||
objectServerRendering = true;
|
||||
ObjectSet set = server.getObjectSet();
|
||||
ObjectSet set = objectServer.getObjectSet();
|
||||
frameSources.forEach(FrameSource::disable);
|
||||
set.enable();
|
||||
|
||||
|
@ -483,7 +509,7 @@ public class MainController implements Initializable, FrequencyListener, MidiLis
|
|||
|
||||
private void disableObjectServerRendering() {
|
||||
Platform.runLater(() -> {
|
||||
server.getObjectSet().disable();
|
||||
objectServer.getObjectSet().disable();
|
||||
objectServerRendering = false;
|
||||
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