機械学習基礎理論独習

誤りがあればご指摘いただけると幸いです。数式が整うまで少し時間かかります。リンクフリーです。

勉強ログです。リンクフリーです
目次へ戻る

【Form/C#】waveファイルを解析する

はじめに

waveファイルの仕様についてはググってください。
非常にわかりやすいフォーマットになっているので、すぐ理解できると思います。
本記事ではwaveファイルを読み込んで各値を取得するプログラムを示します。

プロジェクト

プロジェクトはC#のフォームアプリを選択してください。

Form1.cs[デザイン]

デザインは以下のような感じです。

waveファイルを読み込むと以下のようになります。

Form1.cs

namespace SampleFormWave
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new();
            openFileDialog.Filter = "wave files (*.wav)|";
            openFileDialog.Multiselect = false;

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                string[] filenames = openFileDialog.FileNames;
                WaveReader wr = new();
                wr.read(filenames[0]);
                // show
                labelFilePath.Text = wr.FilePath;
                labelRealFileSize.Text = wr.RealFileSize.ToString();
                labelRiffHeader.Text = wr.RiffHeader;
                labelFileSize.Text = wr.FileSize.ToString();
                labelWaveHeader.Text = wr.WaveHeader;
                labelFormatChunk.Text = wr.FormatChunk;
                labelFormatChunkSize.Text = wr.FormatChunkSize.ToString();
                labelFormatID.Text = wr.FormatID.ToString();
                labelChannel.Text = wr.Channel.ToString();
                labelSampleRate.Text = wr.SampleRate.ToString();
                labelBytePerSec.Text = wr.BytePerSec.ToString();
                labelBlockSize.Text = wr.BlockSize.ToString();
                labelBitPerSample.Text = wr.BitPerSample.ToString();
                labelDataChunk.Text = wr.DataChunk;
                labelDataChunkSize.Text = wr.DataChunkSize.ToString();
                labelPlayTimeMsec.Text = wr.PlayTimeMsec.ToString();
            }
        }
    }
}

WaveReader.cs

waveファイルを読み込むクラスです。

using System.Text;

namespace SampleFormWave
{
    internal class WaveReader
    {
        public string FilePath;
        public int RealFileSize;

        public string RiffHeader;
        public int FileSize;
        public string WaveHeader;
        public string FormatChunk;
        public int FormatChunkSize;
        public int FormatID;
        public int Channel;
        public int SampleRate;
        public int BytePerSec;
        public int BlockSize;
        public int BitPerSample;
        public string DataChunk;
        public int DataChunkSize;
        public int PlayTimeMsec;

        /// <summary>
        /// constructor
        /// </summary>
        public WaveReader()
        { 
        }

        /// <summary>
        /// read wave file
        /// </summary>
        /// <param name="waveFilePath">path of wave file</param>
        public void read(string waveFilePath)
        {
            // confirm file exists
            if (!File.Exists(waveFilePath))
            {
                return;
            }

            using (FileStream fs = new(waveFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                try
                {
                    BinaryReader br = new(fs);
                    this.FilePath = waveFilePath;
                    this.RealFileSize = (int)fs.Length;
                    this.RiffHeader = Encoding.GetEncoding(20127).GetString(br.ReadBytes(4));
                    this.FileSize = BitConverter.ToInt32(br.ReadBytes(4), 0);
                    this.WaveHeader = Encoding.GetEncoding(20127).GetString(br.ReadBytes(4));

                    bool readFmtChunk = false;
                    bool readDataChunk = false;
                    while (!readFmtChunk || !readDataChunk)
                    {
                        // red chunk
                        string chunk = Encoding.GetEncoding(20127).GetString(br.ReadBytes(4));

                        if (chunk.ToLower().CompareTo("fmt ") == 0)
                        {
                            // read fmt chunk
                            this.FormatChunk = chunk;
                            this.FormatChunkSize = BitConverter.ToInt32(br.ReadBytes(4), 0);
                            this.FormatID = BitConverter.ToInt16(br.ReadBytes(2), 0);
                            this.Channel = BitConverter.ToInt16(br.ReadBytes(2), 0);
                            this.SampleRate = BitConverter.ToInt32(br.ReadBytes(4), 0);
                            this.BytePerSec = BitConverter.ToInt32(br.ReadBytes(4), 0);
                            this.BlockSize = BitConverter.ToInt16(br.ReadBytes(2), 0);
                            this.BitPerSample = BitConverter.ToInt16(br.ReadBytes(2), 0);

                            readFmtChunk = true;
                        }
                        else if (chunk.ToLower().CompareTo("data") == 0)
                        {
                            // read data chunk
                            this.DataChunk = chunk;
                            this.DataChunkSize = BitConverter.ToInt32(br.ReadBytes(4), 0);

                            // compute play time
                            int bytesPerSec = this.SampleRate * this.BlockSize;
                            this.PlayTimeMsec = (int) (((double) this.DataChunkSize / (double) bytesPerSec) * 1000);
                            
                            readDataChunk = true;
                        }
                        else
                        {
                            // read chunk
                            Int32 size = BitConverter.ToInt32(br.ReadBytes(4), 0);
                            if (0 < size)
                            {
                                br.ReadBytes(size);
                            }
                        }
                    }
                }
                catch
                {
                    fs.Close();
                }
            }
        }

    }
}
目次へ戻る