「TAURI」にも必要な「Rust」の「クレート」を使う

2023年11月16日(木)
大西 武 (オオニシ タケシ)
第5回の今回は、「TAURI」にも必要な「Rust」の追加機能である「クレート」の使い方やプログラミング方法について解説します。

サウンドを扱う「kira」クレート

今度は「Ogg」形式などのサウンドファイルを読み込んで再生するだけの「kira」クレートの使い方を解説します。このkiraクレートはゲームサウンドの再生向けだそうです。

サンプルプロジェクトのzipファイルをダウンロードすれば「sound」フォルダにサンプルのOggファイルが入っています。Ogg形式のファイルはWindowsの場合なら次のURLの「えこでこツール」などで「Wav」ファイルや「Mp3」ファイルからOggファイルに変換できます。Windowsの場合だけ説明しましたが、筆者はmacOSの「GarageBand」という音楽アプリを使ってサウンドをWavファイルに書き出しました。

・えこでこツールのURL
https://www.vector.co.jp/soft/winnt/art/se445019.html

プロジェクトの作成

まず、Rustプロジェクトの作成からです。Tauriプロジェクトではありません。「Rust」などのフォルダをカレントフォルダにして、ターミナルで次のコマンドを実行して「sound」プロジェクトを新規作成します。プロジェクト名は任意の名前で構いません。それからカレントフォルダを作成されたsoundフォルダに変更します。

・soundプロジェクトの作成
$ cargo new sound

「Cargo.toml」ファイルにクレートを追記

サウンドを扱うkiraクレートをsoundプロジェクトに加えましょう。それからkiraクレートを使う設定を次のように「Cargo.toml」ファイルに追記します。さらにファイルを開くダイアログを扱う「native-dialog」クレートの設定も追加します。これで2つのクレートをrsファイル内で使えるようになり、ビルド時にダウンロードやコンパイルされます。

・「Cargo.toml」ファイルに追記
[package]
name = "sound"
version = "0.1.0"
edition = "2021"

[dependencies]
kira = "0.8.5" # サウンドのクレート
native-dialog = "0.6.4" # ファイルダイアログのクレート

「src」→「main.rs」ファイルでサウンド再生

次のサンプルコードのように「src」→「main.rs」ファイルでkiraクレートを使ってサウンドを再生してみましょう。「cargo run」すれば下図のように「ドレミ」の音が再生されます。本来なら何行もコードを書かなければならないところ、kiraクレートを使えば20行にも満たないコードでサウンドを読み込んで再生できます。

「sleep」関数で1秒ずつ止まっているのは、もし止まることなく「main」関数を終了してしまうと、サウンドもメモリから解放されて再生されることなく終わってしまうからです。

図3:Visual Studio Codeでsoundプロジェクトをビルド

・soundプロジェクトのサンプルコード
// サウンドを扱うクレート
use kira::{
	manager::{AudioManager, AudioManagerSettings,backend::DefaultBackend},
	sound::static_sound::{StaticSoundData, StaticSoundSettings},
};
//スレッドを扱うクレート
use std::thread;
//時間の間隔を扱うクレート
use std::time::Duration;
//メイン関数
fn main() {
  // オーディオマネージャの生成
  let mut manager = AudioManager::::new(AudioManagerSettings::default()).unwrap();
  //サウンド配列 
  let sound_data = vec!{
    //サウンドの読み込み
    StaticSoundData::from_file("C4.ogg", StaticSoundSettings::default()).unwrap(),
    //サウンドの読み込み
    StaticSoundData::from_file("D4.ogg", StaticSoundSettings::default()).unwrap(),
    //サウンドの読み込み
    StaticSoundData::from_file("E4.ogg", StaticSoundSettings::default()).unwrap(),
  };
  //forループ
  for i in 0..3 {
    //サウンドの再生
    manager.play(sound_data[i].clone()).unwrap();
    //1秒スリープ
    thread::sleep(Duration::from_millis(1000));
  }
}

【サンプルコードの解説】
use文でkiraクレートのオーディオマネージャとスタティックサウンドの構造体を使えるようにします。またスレッドと時間の間隔を扱うクレートも使えるようにします。
メイン関数で「AudioManager」構造体のコンストラクタ(newメソッド)でインスタンスを生成し「manager」変数に代入します。
「ド(C4.ogg)」「レ(D4.ogg)」「ミ(E4.ogg)」サウンドファイルを「StaticSoundData」構造体の「from_file」メソッドで読み込んで、「vec!」マクロで「sound_data」配列に代入します。
オーディオマネージャの「play」メソッドで「sound_data」配列の0~3未満の要素のサウンドを順番に再生します。この際スレッドの「sleep」関数で1秒スリープして止まることで1秒ごとにドレミを再生します。

ファイルダイアログでサウンドファイルを開いて再生

今度は自分で開くファイルを選んでからサウンドを再生します(図4)。ファイルダイアログは開くファイルのパス名を取得するだけで、実際にパス名のファイルを開くのはkiraクレートの役割です。

皆さんご存じの通り、ファイルを開くダイアログは前ページのファイルを名前を付けて保存するダイアログと違い、既存のファイル名を選択しても上書き確認されることなくファイルを開くことができます。

図4:ファイルを開くダイアログ

・サウンドファイルを開くサンプルコード
use kira::{
	manager::{AudioManager, AudioManagerSettings,backend::DefaultBackend},
	sound::static_sound::{StaticSoundData, StaticSoundSettings},
};
//ファイルダイアログを扱うクレート
use native_dialog::FileDialog;
use std::thread;
use std::time::Duration;

fn main() {
  let mut manager = AudioManager::::new(AudioManagerSettings::default()).unwrap();
  //ファイルダイアログ
  let path = FileDialog::new()
  //最初にデスクトップを開く
  .set_location("~/Desktop")
  //ファイルの種類をOggだけに
  .add_filter("Ogg Sound", &["ogg"])
  //開くダイアログ
  .show_open_single_file()
  //失敗した場合を無視
  .unwrap();
  //パスの場合分け
  match path {
    //パス名が存在した場合
    Some(path) => {
      //サウンドの読み込み
      let sound_data = StaticSoundData::from_file(path, StaticSoundSettings::default()).unwrap();
      //サウンドの再生
      manager.play(sound_data.clone()).unwrap();
      //2秒スリープ
      thread::sleep(Duration::from_millis(2000));
    },
    //パス名がない場合
    None => return,
  };
}

【サンプルコードの解説】
use文で「native_dialog」クレートの「FileDialog」構造体を使えるようにします。
FileDialog構造体のコンストラクタ(newメソッド)でインスタンスを生成し「path」変数に代入します。「set_location("~/Desktop")」メソッドで最初に開くフォルダをデスクトップにします。「add_filter("Ogg Sound", &["ogg"])」メソッドでファイルの種類を「Ogg」拡張子だけにします。「show_open_single_file()」メソッドでファイルダイアログの種類を1ファイルだけ開くダイアログにセットします。
path変数にパス名が存在する場合はパス名のサウンドを、オーディオマネージャのplayメソッドで2秒間再生します。パス名が存在しない場合はreturnでmain関数を抜け出します。

【コラム】「スピーカー」

今回サウンドを再生することになり、困ったことがありました。筆者の作業場のWindowsマシンのサウンドドライバがどうしても認識しないのです。Intel iMacのBootcampなのでHDMIでディスプレイに繋いでいるわけでもなく一体型のディスプレイです。そこでUSBスピーカーを買ったら正常にサウンドが鳴りました。最近はBluetoothスピーカーが主流かもしれませんが、結局は電源を有線で繋がなければならないので、USBで電源も供給するUSBスピーカーを選びました。

おわりに

今回は、次回からTAURIを本格的にプログラミングしていく際に避けては通れないクレートの使い方を解説しました。クレートを使えば面倒な機能を簡単に扱えるようになることがよくあります。画像とサウンドのクレートは今後も登場します。今度はTAURIの中で使う予定です。

著者
大西 武 (オオニシ タケシ)
1975年香川県生まれ。大阪大学経済学部経営学科中退。プログラミング入門書など30冊以上を商業出版する作家。Microsoftで大賞やNTTドコモでグランプリなど20回以上全国区のコンテストに入賞するアーティスト。オリジナルの間違い探し「3Dクイズ」が全国放送のTVで約10回出題。
https://profile.vixar.jp

連載バックナンバー

開発言語技術解説
第15回

「TAURI」でデータベースを使ってみよう

2024/5/10
第15回の今回は「TAURI」でオープンソースのデータベース「SQLite3」を使用して、テーブル表に表示する解説をしていきます。
開発言語技術解説
第14回

「TAURI」で気象庁の「CSVデータ」を解析する

2024/5/1
第14回の今回は気象庁のWebサイトから指定した地域の1年間の気象データをダウンロードして「TAURI」で解析していきます。
開発言語技術解説
第13回

「TAURI」で「簡易RSSリーダー」を開発してみよう

2024/4/16
第13回の今回は「TAURI」で「RSSフィード」を読み込んでWebページに一覧表示し、リンクのページを開くための新規ウィンドウを作成するところまでを解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています