我正在开发一个程序,该程序将能够使用来自麦克风或Line-in的流式幅度数据绘制音频波形。我认为这样做的方法是以等于采样率的速率从采样数据中绘制每个点,并在每个方向上沿x方向绘制1步。因此,我需要大约每秒44100次更新JavaFx Application线程以绘制每个点。在开始执行此操作之前,我想通过画一条直线并每半秒更新一次每个点来检验我的想法。我正在使用时间轴类来做到这一点。我的代码如下:
public class JavaFxPractice extends Application {
private int xValue = 50;
@Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
EventHandler<ActionEvent> eventHandler = e -> {
xValue++;
Line point = new Line(xValue,50,xValue,50);
pane.getChildren().add(point);
};
Timeline animation = new Timeline(new KeyFrame(Duration.millis((500)), eventHandler));
animation.setCycleCount(500);
animation.play();
Scene scene = new Scene(pane, 600, 500);
primaryStage.setTitle("Streaming Test");
primaryStage.setScene(scene);
primaryStage.show();
}
}
但是,每次执行此操作时,我的程序都变得无响应,必须强制关闭它。我注意到,如果我做同样的事情,但是使Text闪烁,则效果很好。是否存在无法使用“时间轴”类绘制线的原因?它会给线程带来过多的负担吗?如果是这样,我该如何解决我的想法。我只希望能够实时绘制波形,并以每秒约44,100次的速度更新。
对于任何正在进行的动画,我建议AnimationTimer
。它尝试尽可能快地更新到接近60 fps。 (我只是在第一个评论之后读了一些评论,推荐AnimationTimer
。这些人是对的。IDK为什么他们自己没有将其发布为答案。)
然后问题变成要显示的内容。如果我正在攻击此问题,请尝试以下操作:
ConcurrentLinkedQueue
)ConcurrentLinkedQueue
的读取内容加载到AudioInputLine
中>ConcurrentLinkedQueue
的轮询AnimationTimer
要获得计时的时间,您可能需要使用抽取(例如,每3个或更多PCM数据点中的第2个或第2个扔掉),或者如果无法轻松进行所需的抽取,则使用线性插值使用有理分数。换句话说,您不受阵列(附加像素)和PCM数据点之间1:1对应的束缚。您使用的抽取越多,丢失的高频就会越多。