| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package audiovisualizer3d; |
| |
| import javafx.animation.Timeline; |
| import javafx.application.Application; |
| import javafx.scene.DepthTest; |
| import javafx.scene.Group; |
| import javafx.scene.Node; |
| import javafx.scene.PerspectiveCamera; |
| import javafx.scene.Scene; |
| import javafx.scene.media.AudioSpectrumListener; |
| import javafx.scene.media.Media; |
| import javafx.scene.media.MediaPlayer; |
| import javafx.scene.paint.Color; |
| import javafx.scene.shape.RectangleBuilder; |
| import javafx.scene.transform.Rotate; |
| import javafx.scene.transform.Scale; |
| import javafx.scene.transform.Translate; |
| import javafx.stage.Stage; |
| |
| /** |
| * A sample that demonstrates a 3D animated audio visualizer sample. When the |
| * application runs in standalone mode, the scene must be constructed with |
| * the depthBuffer argument set to true, and the root node must have depthTest |
| * set to true. |
| * |
| * @see javafx.scene.media.AudioSpectrumListener |
| * @see javafx.scene.media.MediaPlayer |
| * @see javafx.scene.shape.RectangleBuilder |
| * @see javafx.scene.paint.Color |
| * @see javafx.scene.Group |
| * @see javafx.scene.transform.Rotate |
| * @see javafx.scene.transform.Scale |
| */ |
| public class AudioVisualizer3D extends Application implements AudioSpectrumListener { |
| |
| Xform cubeXform[]; |
| Cube cube[]; |
| |
| private void init(Stage primaryStage) { |
| Group root = new Group(); |
| root.setDepthTest(DepthTest.ENABLE); |
| primaryStage.setResizable(false); |
| primaryStage.setScene(new Scene(root, 400, 500, true)); |
| primaryStage.getScene().setCamera(new PerspectiveCamera()); |
| root.getTransforms().addAll( |
| new Translate(400 / 2, 500 / 2 + 100), |
| new Rotate(180, Rotate.X_AXIS) |
| ); |
| root.getChildren().add(create3dContent()); |
| } |
| |
| private AudioSpectrumListener audioSpectrumListener; |
| |
| private static final String AUDIO_URI = System.getProperty("demo.audio.url","http://download.oracle.com/otndocs/products/javafx/oow2010-2.flv"); |
| private static MediaPlayer audioMediaPlayer; |
| private static final boolean PLAY_AUDIO = Boolean.parseBoolean(System.getProperty("demo.play.audio","true")); |
| |
| @Override public void spectrumDataUpdate(double timestamp, double duration, |
| float[] magnitudes, float[] phases) { |
| for (int i = 0; i < magnitudes.length; i++) { |
| cube[i].s.setX((magnitudes[i] + 60.01)*0.1 + 1.0); |
| cube[i].s.setY((magnitudes[i] + 60.01)*1.5 + 1.0); |
| cube[i].s.setZ((magnitudes[i] + 60.01)*0.8 + 1.0); |
| cubeXform[i].rx.setAngle((magnitudes[i] + 60.0)*2.0); |
| cubeXform[i].ry.setAngle((magnitudes[i] + 60.0)*2.1 + 10.0); |
| cubeXform[i].rz.setAngle((magnitudes[i] + 60.0)*2.1 + 10.0); |
| cubeXform[i].setTranslateY((magnitudes[i] + 60.0)*-1.0); |
| } |
| } |
| |
| public void play() { |
| this.startAudio(); |
| } |
| |
| @Override public void stop() { |
| this.stopAudio(); |
| } |
| |
| public Node create3dContent() { |
| |
| Xform sceneRoot = new Xform(); |
| |
| cubeXform = new Xform[128]; |
| cube = new Cube[128]; |
| |
| int i; |
| for (i = 0; i < 128; i++) { |
| cubeXform[i] = new Xform(); |
| cubeXform[i].setTranslateX((double) 2); |
| cube[i] = new Cube(1.0, Color.hsb((double) i*1.2, 1.0, 1.0, 0.3), 1.0); |
| if (i == 0) { |
| sceneRoot.getChildren().add(cubeXform[i]); |
| } |
| else if (i >= 1) { |
| cubeXform[i-1].getChildren().add(cubeXform[i]); |
| } |
| cubeXform[i].getChildren().add(cube[i]); |
| } |
| |
| audioSpectrumListener = this; |
| getAudioMediaPlayer().setAudioSpectrumListener(audioSpectrumListener); |
| getAudioMediaPlayer().play(); |
| getAudioMediaPlayer().setAudioSpectrumInterval(0.02); |
| getAudioMediaPlayer().setAudioSpectrumNumBands(128); |
| getAudioMediaPlayer().setCycleCount(Timeline.INDEFINITE); |
| |
| sceneRoot.setRotationAxis(Rotate.X_AXIS); |
| sceneRoot.setRotate(180.0); |
| sceneRoot.setTranslateY(-100.0); |
| |
| return sceneRoot; |
| } |
| |
| class Xform extends Group { |
| final Rotate rx = new Rotate(0, Rotate.X_AXIS); |
| final Rotate ry = new Rotate(0, Rotate.Y_AXIS); |
| final Rotate rz = new Rotate(0, Rotate.Z_AXIS); |
| public Scale s = new Scale(); |
| public Xform() { |
| super(); |
| getTransforms().addAll(rz, ry, rx, s); |
| } |
| } |
| |
| public class Cube extends Group { |
| final Rotate rx = new Rotate(0,Rotate.X_AXIS); |
| final Rotate ry = new Rotate(0,Rotate.Y_AXIS); |
| final Rotate rz = new Rotate(0,Rotate.Z_AXIS); |
| public Scale s = new Scale(); |
| public Cube(double size, Color color, double shade) { |
| getTransforms().addAll(rz, ry, rx, s); |
| getChildren().addAll( |
| RectangleBuilder.create() // back face |
| .width(size).height(size) |
| .fill(color.deriveColor(0.0, 1.0, (1 - 0.5*shade), 1.0)) |
| .translateX(-0.5*size) |
| .translateY(-0.5*size) |
| .translateZ(0.5*size) |
| .build(), |
| RectangleBuilder.create() // bottom face |
| .width(size).height(size) |
| .fill(color.deriveColor(0.0, 1.0, (1 - 0.4*shade), 1.0)) |
| .translateX(-0.5*size) |
| .translateY(0) |
| .rotationAxis(Rotate.X_AXIS) |
| .rotate(90) |
| .build(), |
| RectangleBuilder.create() // right face |
| .width(size).height(size) |
| .fill(color.deriveColor(0.0, 1.0, (1 - 0.3*shade), 1.0)) |
| .translateX(-1*size) |
| .translateY(-0.5*size) |
| .rotationAxis(Rotate.Y_AXIS) |
| .rotate(90) |
| .build(), |
| RectangleBuilder.create() // left face |
| .width(size).height(size) |
| .fill(color.deriveColor(0.0, 1.0, (1 - 0.2*shade), 1.0)) |
| .translateX(0) |
| .translateY(-0.5*size) |
| .rotationAxis(Rotate.Y_AXIS) |
| .rotate(90) |
| .build(), |
| RectangleBuilder.create() // top face |
| .width(size).height(size) |
| .fill(color.deriveColor(0.0, 1.0, (1 - 0.1*shade), 1.0)) |
| .translateX(-0.5*size) |
| .translateY(-1*size) |
| .rotationAxis(Rotate.X_AXIS) |
| .rotate(90) |
| .build(), |
| RectangleBuilder.create() // top face |
| .width(size).height(size) |
| .fill(color) |
| .translateX(-0.5*size) |
| .translateY(-0.5*size) |
| .translateZ(-0.5*size) |
| .build() |
| ); |
| } |
| } |
| |
| private void startAudio() { |
| if (PLAY_AUDIO) { |
| getAudioMediaPlayer().setAudioSpectrumListener(audioSpectrumListener); |
| getAudioMediaPlayer().play(); |
| } |
| } |
| |
| private void stopAudio() { |
| if (getAudioMediaPlayer().getAudioSpectrumListener() == audioSpectrumListener) { |
| getAudioMediaPlayer().pause(); |
| } |
| } |
| |
| private static MediaPlayer getAudioMediaPlayer() { |
| if (audioMediaPlayer == null) { |
| Media audioMedia = new Media(AUDIO_URI); |
| audioMediaPlayer = new MediaPlayer(audioMedia); |
| } |
| return audioMediaPlayer; |
| } |
| |
| @Override public void start(Stage primaryStage) throws Exception { |
| init(primaryStage); |
| primaryStage.show(); |
| play(); |
| } |
| |
| /** |
| * The main() method is ignored in correctly deployed JavaFX |
| * application. main() serves only as fallback in case the |
| * application can not be launched through deployment artifacts, |
| * e.g., in IDEs with limited FX support. NetBeans ignores main(). |
| * @param args the command line arguments |
| */ |
| public static void main(String[] args) { |
| launch(args); |
| } |
| } |