WinFormsアプリケーションでのサウンド再生方法

2024年8月29日

この資料では、WinFormsアプリケーションでサウンドを再生する基本的な方法を紹介します。各方法の特徴と使用例を通じて、あなたのアプリケーションに最適な方法を見つける手助けをします。

WinFormsアプリケーションにおけるサウンド再生の基礎

サウンド再生の基本

System.Media.SoundPlayer クラスの使用

System.Media.SoundPlayer クラスは、WAVファイルを簡単に再生するためのクラスです。シンプルな通知音などに適しています。

サンプルコード:

using System;
using System.Media;
using System.Windows.Forms;

namespace SoundApp
{
    partial class Form1 : Form
    {
        private Button playSoundButton;

        public Form1()
        {
            playSoundButton = new Button();
            playSoundButton.Text = "Play Sound";
            playSoundButton.Click += PlaySoundButton_Click;
            Controls.Add(playSoundButton);
        }

        private void PlaySoundButton_Click(object sender, EventArgs e)
        {
            using (SoundPlayer player = new SoundPlayer(@"fanfare.wav"))
            {
                player.Load();
                player.Play();
            }
        }
    }
}

ポイント:

  • SoundPlayer クラスはWAVファイルのみをサポート。
  • シンプルで使いやすい。
using (SoundPlayer player = new SoundPlayer(@"fanfare.wav"))
{
    player.Load();
    player.Play();
}

SoundPlayer player = new SoundPlayer(@"fanfare.wav");

player.Play();

に差し替えてみてください(改行を必要とされることがあります。現在、原因は不明です)

SoundPlayer の Load メソッドを使用せずに直接 Play メソッドを呼び出す場合に正常に実行できる理由は、Load メソッドが呼び出されなくても Play メソッドが内部で自動的に音声ファイルをロードするためです。

詳細な説明

  1. 自動ロードの動作:
    • SoundPlayer クラスの Play メソッドは、音声ファイルがまだロードされていない場合、内部で自動的に音声ファイルをロードします。したがって、Load メソッドを明示的に呼び出さなくても、Play メソッドは音声ファイルをロードして再生を開始します。このため、直接 Play メソッドを呼び出しても動作します。
  2. リソースの解放:
    • using ステートメントを使用しない場合、リソースの解放が自動的に行われませんが、SoundPlayer オブジェクトがガベージコレクションにより回収されるときに、リソースが解放されます。ただし、これは即座に解放されるわけではなく、ガベージコレクターのタイミングによります。短期間の使用であれば、この影響は限定的かもしれません。

正常に実行できる理由のまとめ

  • 自動ロード機能SoundPlayer.Play メソッドは、音声ファイルがまだロードされていない場合に自動的にロードします。
  • ガベージコレクションusing ステートメントを使用しない場合でも、最終的にはガベージコレクションによりリソースが解放されるため、短期間の使用では問題が発生しないことがあります。

例外となるケース

  • Windows 11のデバイスガードが特定のコードパスをブロックする場合があります。これは、セキュリティ設定やポリシーによるものであり、特定のメソッド呼び出し(例えば、Load メソッド)が制限される可能性があります。using ステートメントや Load メソッドの使用がセキュリティポリシーに影響を与えることもあります。

正常に実行できる場合とできない場合の違いは、これらの要因の組み合わせによるものです。具体的な環境や設定によって動作が変わる可能性がありますので、詳細なセキュリティ設定やポリシーの確認が必要です。

多様なサウンドフォーマットのサポート

System.Windows.Media.MediaPlayer クラスの使用

System.Windows.Media.MediaPlayer クラスは、MP3などの多様なオーディオフォーマットをサポートします。

必要なアセンブリの参照追加
  1. WPFアセンブリの追加 プロジェクトに以下のアセンブリを追加する必要があります。
    • PresentationCore
    • PresentationFramework
    • WindowsBase

プロジェクトをみ

プロジェクトの設定
  1. プロジェクトの参照設定
    • ソリューションエクスプローラーでプロジェクト内の参照を右クリックし、「参照の追加」を選択します。
    • 「アセンブリ」タブを選択し、リストから PresentationCorePresentationFrameworkWindowsBaseをチェックして追加します。

サンプルコード:

using System;
using System.Windows.Forms;
using System.Windows.Media;

namespace SoundApp
{
    partial class Form1 : Form
    {
        private Button playSoundButton;
        private MediaPlayer mediaPlayer;

        public Form1()
        {
            playSoundButton = new Button();
            playSoundButton.Text = "Play Sound";
            playSoundButton.Click += PlaySoundButton_Click;
            Controls.Add(playSoundButton);

            mediaPlayer = new MediaPlayer();
        }

        private void PlaySoundButton_Click(object sender, EventArgs e)
        {
            mediaPlayer.Open(new Uri(@"fanfare.wav", UriKind.Relative));
            mediaPlayer.Play();
        }
    }
}

ポイント:

  • WAV以外のオーディオフォーマットをサポート。
  • WPFとWinFormsの統合が必要。

都度、ファイルのオープンをしないようにする、ボタンを押すごとにサウンドを最初から再生されるよにする

using System;
using System.Windows.Forms;
using System.Windows.Media;

namespace SoundApp
{
    partial class Form1 : Form
    {
        private Button playSoundButton;
        private MediaPlayer mediaPlayer;

        public Form1()
        {
            InitializeComponent();

            playSoundButton = new Button();
            playSoundButton.Text = "Play Sound";
            playSoundButton.Click += PlaySoundButton_Click;
            Controls.Add(playSoundButton);

            InitializeMediaPlayer();
        }

        private void InitializeMediaPlayer()
        {
            mediaPlayer = new MediaPlayer();
            Uri soundUri = new Uri(@"fanfare.wav", UriKind.Relative);
            mediaPlayer.Open(soundUri);
        }


        private void PlaySoundButton_Click(object sender, EventArgs e)
        {
            // 再生前にメディアプレイヤーの位置をリセットする
            mediaPlayer.Position = TimeSpan.Zero;
            mediaPlayer.Play();
        }
    }
}

解説

メディアプレイヤーの初期化

private void InitializeMediaPlayer()
{
    mediaPlayer = new MediaPlayer();
    Uri soundUri = new Uri(@"fanfare.wav", UriKind.Relative);
    mediaPlayer.Open(soundUri);
}
  • InitializeMediaPlayer()MediaPlayerの初期化を行うメソッド。
  • mediaPlayer = new MediaPlayer()MediaPlayerオブジェクトを作成。
  • Uri soundUri = new Uri(@"fanfare.wav", UriKind.Relative):相対パスでサウンドファイルのURIを作成
  • mediaPlayer.Open(soundUri)MediaPlayerにサウンドファイルを開く。

ボタンクリックイベントハンドラ

private void PlaySoundButton_Click(object sender, EventArgs e)
{
    // 再生前にメディアプレイヤーの位置をリセットする
    mediaPlayer.Position = TimeSpan.Zero;
    mediaPlayer.Play();
}
  • PlaySoundButton_Click(object sender, EventArgs e):ボタンがクリックされたときに呼び出されるイベントハンドラ。
  • mediaPlayer.Position = TimeSpan.Zero:再生位置を先頭にリセット。
  • mediaPlayer.Play():サウンドを再生する。

現象:

フォームを継承したクラス内で使用した場合、デザイン設計時より画面が小さくなります

考えられる原因:

MediaPlayerクラスが、WPFアプリ用のクラスのための弊害(ビジュアルの違い)

対応

AxWindowsMediaPlayerクラスへの置き換え

ツールボックスにコントロールの追加

COMコンポーネント、Windows Media Playerを選択、OK
(すでに選ばれている時、一度解除してOK、再度右クリックメニューから行ってください)

ツールボックスのコントロールを配置

ツールボックスにWindows Media Playerが追加されているのを確認、フォームのデザインにドラッグ&ドロップ

参照情報が更新されるのを確認

ソリューションエクスプローラーの参照にAxWMPLibとWMPLibが追加されているのを確認

一時的な配置コントロールの削除

一度、ドラッグ&ドロップドロップしたコントロールは削除して構いません
また、通常のようにビジュアルコントロールとして使用することもできます

コードのクラス置き換え

サンプルコードを参考にMediaPlayerクラスを置き換えます

using System;
using System.Windows.Forms;
using AxWMPLib;

namespace SoundApp
{
    public partial class Form1 : Form
    {
        private Button playSoundButton;
        private AxWindowsMediaPlayer axWindowsMediaPlayer;

        public Form1()
        {
            InitializeComponent();
            
            playSoundButton = new Button();
            playSoundButton.Text = "Play Sound";
            playSoundButton.Click += PlaySoundButton_Click;
            Controls.Add(playSoundButton);

            axWindowsMediaPlayer = new AxWindowsMediaPlayer();
            axWindowsMediaPlayer.CreateControl(); // コントロールを作成
        }

        private void PlaySoundButton_Click(object sender, EventArgs e)
        {
            axWindowsMediaPlayer.URL = "fanfare.wav";
            axWindowsMediaPlayer.Ctlcontrols.play();
        }
    }
}

ループ再生したいとき

// ループ再生を有効にする
axWindowsMediaPlayer.settings.setMode("loop", true);

// 再生開始
axWindowsMediaPlayer.Ctlcontrols.play();

高度なサウンド操作

NAudio ライブラリの使用

NAudio ライブラリは、より高度なサウンド再生や操作をサポートします。

NAudio パッケージのインストール

NuGetパッケージマネージャを使用して、NAudio パッケージをインストールします。

サンプルコード:

using System;
using System.Windows.Forms;
using NAudio.Wave;

namespace SoundApp
{
    partial class Form1 : Form
    {
        private Button playSoundButton;
        private WaveOutEvent waveOut;
        private AudioFileReader audioFileReader;

        public Form1()
        {
            playSoundButton = new Button();
            playSoundButton.Text = "Play Sound";
            playSoundButton.Click += PlaySoundButton_Click;
            Controls.Add(playSoundButton);

            waveOut = new WaveOutEvent();
        }

        private void PlaySoundButton_Click(object sender, EventArgs e)
        {
            if (audioFileReader != null)
            {
                audioFileReader.Dispose();
            }

            audioFileReader = new AudioFileReader("fanfare.wav");
            waveOut.Init(audioFileReader);
            waveOut.Play();
        }
    }
}

ポイント:

  • 高度なオーディオ機能を提供。
  • 多様なオーディオフォーマットと操作に対応。

まとめ

この資料では、WinFormsアプリケーションでサウンドを再生する3つの方法を紹介しました。各方法にはそれぞれの利点があり、用途に応じて使い分けることが重要です。基本的な通知音には System.Media.SoundPlayerを、複数のオーディオフォーマットを扱う場合には System.Windows.Media.MediaPlayer を、高度なオーディオ操作が必要な場合には NAudio ライブラリを使用することをお勧めします。


参考リンク