JavaFX多媒體(1)使用Audio Clip播放音訊
|
在Java Swing中欲處理音訊與影像,需額外安裝Java Media Framework (JMF),JMF為Java S.E.的選項套件,目前版本為JMF 2.1.1.e,支援以下之應用:
JMF並支援以下的音訊與影像格式:
但JMF 2.1.1.e自2003年5月發表以來則沒有任何更新,因此許多新的媒體格式均無法正常運作。此外,由於JMF屬於Java S.E.的選項套件,因此在使用之前必須安裝與設定。 JavaFX內建支援處理音訊與影像的API,分為Audio Clip與Media,前者僅處理播放簡短音訊;後者則類似於Java Media Framework,可播放音訊與影像。 JavaFX支援以下的音訊與影像編碼:
JavaFX支援以下的音訊與影像格式:
分別由以下類別處理:
以下類別處理音訊等化器 (Audio Equalizer):
以下類別處理媒體事件:
在JavaFX中欲播放簡短音訊,可使用javafx.scene.media.AudioClip類別,類似於Java AWT的AudioClip介面。 AudioClip類別定義以下的屬性值:
AudioClip類別的方法包括:
須注意的是上述設定方法,其設定值並不會影響正在播放中的音訊,只有在下一次執行play()方法播放音訊時才會生效。 請參考以下範例示範以滑動軸與核取方塊設定音量平衡、重覆播放次數、音量平移、播放速率與音量大小。當移動滑動軸時,則以滑動軸目前的值分別設定上述屬性。當點選核取方塊時,則設定重覆播放次數為AudioClip.INDEFINITE,代表無限次數: CheckBox checkbox;
Slider slider1, slider2, slider3, slider4, slider5;
...
// 設定音量平衡
slider1 = new Slider();
...
slider1.valueProperty().addListener(new ChangeListener<Number>() {
@Override public void changed(
ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) {
// 設定音量平衡
audioclip.setBalance(slider1.getValue());
lblValue1.setText(new DecimalFormat("0.0").format(
slider1.getValue()));
}
});
// 設定重覆播放次數
slider2 = new Slider();
...
slider2.valueProperty().addListener(new ChangeListener<Number>() {
@Override public void changed(
ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) {
// 設定重覆播放次數
audioclip.setCycleCount((int)slider2.getValue());
lblValue2.setText(new DecimalFormat("0").format(
slider2.getValue()));
}
});
checkbox = new CheckBox("Indefinite");
checkbox.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override public void changed(ObservableValue observable,
Boolean oldValue, Boolean newValue) {
// 設定重覆播放次數
audioclip.setCycleCount(
newValue? AudioClip.INDEFINITE : (int)slider2.getValue());
slider2.setDisable(newValue);
lblValue2.setDisable(newValue);
}
});
由以上範例可以瞭解,AudioClip類別的主要功能僅在於播放與停止播放音訊,並無法處理暫停播放、音訊時間長度、後設資料 (註)、等化器、事件等功能。 【執行結果】 請參考以下範例示範配合滑鼠與按鍵事件,當以滑鼠點選各個長條時,則以AudioClip類別的play()方法分別播放各音階,如同彈琴一般: AudioClip DoAudioClip = new AudioClip(
getClass().getResource("audio/Do.wav").toString());
AudioClip ReAudioClip = new AudioClip(
getClass().getResource("audio/Re.wav").toString());
AudioClip MiAudioClip = new AudioClip(
getClass().getResource("audio/Mi.wav").toString());
AudioClip FaAudioClip = new AudioClip(
getClass().getResource("audio/Fa.wav").toString());
AudioClip SoAudioClip = new AudioClip(
getClass().getResource("audio/So.wav").toString());
AudioClip LaAudioClip = new AudioClip(
getClass().getResource("audio/La.wav").toString());
AudioClip SiAudioClip = new AudioClip(
getClass().getResource("audio/Si.wav").toString());
AudioClip Do2AudioClip = new AudioClip(
getClass().getResource("audio/Do2.wav").toString());
Group DoBar = createBar(Color.RED, Color.ORANGE,
27.0, 100.0, 20.0, 80.0);
Group ReBar = createBar(Color.ORANGE, Color.YELLOW,
49.0, 100.0, 20.0, 80.0);
Group MiBar = createBar(Color.YELLOW, Color.GREEN,
71.0, 100.0, 20.0, 80.0);
Group FaBar = createBar(Color.GREEN, Color.BLUE,
93.0, 100.0, 20.0, 80.0);
Group SoBar = createBar(Color.BLUE, Color.INDIGO,
115.0, 100.0, 20.0, 80.0);
Group LaBar = createBar(Color.INDIGO, Color.VIOLET,
137.0, 100.0, 20.0, 80.0);
Group SiBar = createBar(Color.VIOLET, Color.RED,
159.0, 100.0, 20.0, 80.0);
Group Do2Bar = createBar(Color.RED, Color.ORANGE,
181.0, 100.0, 20.0, 80.0);
DoBar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
DoAudioClip.play();
}
});
ReBar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
ReAudioClip.play();
}
});
MiBar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
MiAudioClip.play();
}
});
FaBar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
FaAudioClip.play();
}
});
SoBar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
SoAudioClip.play();
}
});
LaBar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
LaAudioClip.play();
}
});
SiBar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
SiAudioClip.play();
}
});
Do2Bar.setOnMousePressed(new EventHandler() {
@Override public void handle(MouseEvent e) {
Do2AudioClip.play();
}
});
Group group = new Group();
group.getChildren().add(DoBar);
group.getChildren().add(ReBar);
group.getChildren().add(MiBar);
group.getChildren().add(FaBar);
group.getChildren().add(SoBar);
group.getChildren().add(LaBar);
group.getChildren().add(SiBar);
group.getChildren().add(Do2Bar);
group.setScaleX(1.5);
group.setScaleY(1.5);
若按下A至K的鍵盤按鍵,同樣以AudioClip類別的play()方法分別播放各音階: // Key Pressed
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override public void handle(KeyEvent e) {
if (e.getCode() == KeyCode.A)
DoAudioClip.play();
else if (e.getCode() == KeyCode.S)
ReAudioClip.play();
else if (e.getCode() == KeyCode.D)
MiAudioClip.play();
else if (e.getCode() == KeyCode.F)
FaAudioClip.play();
else if (e.getCode() == KeyCode.G)
SoAudioClip.play();
else if (e.getCode() == KeyCode.H)
LaAudioClip.play();
else if (e.getCode() == KeyCode.J)
SiAudioClip.play();
else if (e.getCode() == KeyCode.K)
Do2AudioClip.play();
}
});
【執行結果】 除了AudioClip類別之外,亦可使用AudioClipBuilder類別處理音訊,請參考以下範例示範以AudioClipBuilder類別處理音訊,首先以create()方法建立AudioClipBuilder的實體,最後再以build()方法以AudioClipBuilder物件建立AudioClip物件,其間並以上述方法設定音訊的相關屬性,各方法可為任意順序或省略: AudioClip audioclip = null;
URL source = getClass().getResource("audio/Windows.wav");
audioclip = AudioClipBuilder.create()
.source(source.toString())
.balance(0.0)
.cycleCount(1)
.pan(0.0)
.rate(1.0)
.volume(1.0)
.build();
(註):Metadata原意為Data about Data,中文直譯為有關資料的資料或描述資料的資料,國內學者對於Metadata有不同的譯名,常見的有元資料、詮釋資料、超資料等,中央研究院數位典藏與數位學習國家型科技計畫則譯為後設資料,特此說明。請參考中央研究院數位典藏與數位學習國家型科技計畫之說明。在多媒體中,Metadata是指內嵌於音訊與影像檔案中的標籤 (Tag) 資料。 【參考資料】 [1] Java Official Web Site |

Java 學習之路


