Rust 播放 WAV 檔與即時音量控制
Conclusion
// 播放 WAV 檔與即時音量控制
use rodio::{Decoder, Player};
use std::fs::File;
fn main() {
let handle =
rodio::DeviceSinkBuilder::open_default_sink().expect("Error to open default audio stream");
let file = File::open("test.wav").unwrap();
let player = Player::connect_new(handle.mixer());
let source = Decoder::try_from(file).unwrap();
// handle.mixer().add(source);
player.append(source);
std::thread::sleep(std::time::Duration::from_secs(2));
player.set_volume(0.5);
std::thread::sleep(std::time::Duration::from_secs(2));
player.set_volume(1.5);
std::thread::sleep(std::time::Duration::from_secs(2));
}Practice
載入外部套件
cargo add rodio
注意不同版本在用法上有些差異,以最新版為主
Audio Sink
an audio sink is essentially an audio output device or destination. It is a conceptual endpoint (like your physical speakers, headphones, or a Bluetooth headset) where your sound server sends digital audio to be converted into physical sound.
簡單來說,音訊出口為 sink,反之入口為 source。
rodio
要達成音訊播放在 rodio 上有幾個步驟:
- 找到系統實體播放裝置的 sink handle(OS-sink)(
DeviceSinkBuilder::open_default_sink()) - 建立一個串流音訊的物件,例如 sine wave、buffer 或
Decoder等 - 將 source 添加到 OS-sink handle(
MixerDeviceSink::mixer())
Player
除了直接對接 handle 播放之外,如果想要有更多控制選項,可以透過 Player 來播放,像是更改音量大小:
let handle =
rodio::DeviceSinkBuilder::open_default_sink().expect("Error to open default audio stream");
let file = File::open("test.wav").unwrap();
let player = Player::connect_new(&handle.mixer());
let source = Decoder::try_from(file).unwrap();
// handle.mixer().add(source);
player.append(source);MixerDeviceSink
在作業系統的底層音訊架構(如 macOS CoreAudio 或 Linux PipeWire/ALSA)中,實體音效卡(physical device)通常同一個時間只能接收「一條」連續的音訊資料流。
如果你的程式同時要發出兩個獨立的聲音(例如一首歌 + 一個 SFX),硬體是沒辦法自動幫你把兩個檔案疊在一起的。這時候就需要 Mixer 介入。
接收多個音訊源(Sources),在記憶體中將同一個時間點的樣本數值以數學方式相加、處理潛在的取樣率轉換(Resampling),最後打包成「一條」主音軌送給硬體播放。
Associated Functions(關聯函數)
不隸屬於某個特定的實例,而是直接隸屬於型別(type)本身,不使用 self,常用來建構實例,以 :: 表示。
其他一般 function 加上 self 表示它本身需要一個具體物件才能動。
也就是說,:: 表示它與從設計圖開始建造物件有關,而 . 則用在已經建立的物件上。
另外在引入其他 crates 也有看到, :: 有表示路徑的意思