更新JavaFx中的应用程序线程以绘制节点



我正在开发一个程序,该程序将能够使用麦克风或Line in的流式振幅数据绘制音频波形。我想这样做的方法是以与采样率相等的速率从采样数据中绘制每个点,在x方向上绘制每个点一步。因此,我需要每秒更新约44100次JavaFx应用程序线程来绘制每个点。在我开始做这件事之前,我想通过画一条直线来测试我的想法,并且每半秒更新一次每一点。我正在使用Timeline类来完成此操作。我的代码如下:

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闪烁,它会非常好地工作。不能使用Timeline类绘制线条是有原因的吗?这会不会给线程带来太大的负载?如果是,我可以用什么方法来解决我的想法。我只想能够实时绘制波形,每秒更新44100次左右。

对于任何正在进行的动画,我建议使用AnimationTimer。它尝试尽可能接近每秒60帧的速度进行更新。(我刚刚读到第一条评论之后的一些评论,推荐AnimationTimer。这些人是对的。IDK为什么他们自己没有把它作为答案发布。(

然后问题变成了显示什么。如果我要解决这个问题,下面是我要尝试的:

  1. 制作一个数组来保存显示大小的位置,每个像素一个bucket
  2. 制作一个函数,从这样一个数组中提取数据,该数组可以由动画计时器调用
  3. 创建一个并发安全队列来容纳这些数组(例如ConcurrentLinkedQueue(
  4. AudioInputLine的读取加载ConcurrentLinkedQueue
  5. ConcurrentLinkedQueueAnimationTimer的轮询

要计算出计时,您可能需要使用抽取(例如,每2个或3个或更多PCM数据点中的2个(,或者如果所需的抽取没有达到易于使用的有理分数,则需要使用线性插值。换句话说,您不受阵列(与像素相关(和PCM数据点之间1:1对应关系的约束。你使用的抽取越多,丢失的高频就会越多。

最新更新