7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#でWAVE再生

Last updated at Posted at 2019-01-19

概要

C#でwavを動的生成して再生するサンプル。

環境

Visual Studio Community 2017

wavファイルの再生

先ずwavファイル再生のおさらい。
Visual C#のフォームアプリケーションを作成し、フォームにボタンとClickイベントハンドラを作る。そして適当なwavファイルを用意する。

        private void button1_Click(object sender, EventArgs e)
        {
            var player = new SoundPlayer();
            player.SoundLocation = @"c:\tmp\sample.wav";
            player.Load();
            player.Play();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            var player = new SoundPlayer(@"c:\tmp\sample.wav");
            player.Play();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            var stream = File.OpenRead(@"c:\tmp\sample.wav");
            var player = new SoundPlayer(stream);
            player.Play();
        }

wavの動的生成と再生

波形データを生成し、WaveFileHeaderを付けてMemoryStreamに書き込んで再生する。またFileStreamに書き込めばそのままwavファイルとなる。

Form1.cs
using System;
using System.IO;
using System.Media;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace GenerateWave
{
    [StructLayout(LayoutKind.Sequential)]
    class WaveFileHeader
    {
        public uint riff_ckid = 0x46464952;    // "RIFF"
        public uint riff_cksize;
        public uint fccType = 0x45564157;      // "WAVE"
        public uint fmt_ckid = 0x20746d66;     // "fmt "
        public uint fmt_cksize = 16;
        public ushort wFormatTag = 0x0001;     // WAVE_FORMAT_PCM
        public ushort nChannels;
        public uint nSamplesPerSec;
        public uint nAvgBytesPerSec;
        public ushort nBlockAlign;
        public ushort wBitsPerSample;
        public uint data_ckid = 0x61746164;    // "data"
        public uint data_cksize;
    }

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

        private void button1_Click(object sender, EventArgs e)
        {
            const uint sampleRate = 48000;  // サンプリング周波数

            // 波形データの生成
            uint wavelen = sampleRate / 2;
            byte[] wave = new byte[wavelen];

            double t = 0;
            for (uint i = 0; i < wavelen; i++)
            {
                double freq = (i < wavelen / 2) ? 2000 : 1000;
                t = (t + freq / sampleRate) % 1;
                wave[i] = (byte)(128 + (t < 0.5 ? 1 : -1) * 10);
            }

            // WAVEファイルヘッダ
            var wfh = new WaveFileHeader();

            wfh.nChannels = 1;
            wfh.nSamplesPerSec = sampleRate;
            wfh.nAvgBytesPerSec = sampleRate;
            wfh.nBlockAlign = 1;
            wfh.wBitsPerSample = 8;

            wfh.riff_cksize = 36 + wavelen;
            wfh.data_cksize = wavelen;

            //using (FileStream stream = new FileStream(@"c:\tmp\hoge.wav", FileMode.Create))
            using (MemoryStream stream = new MemoryStream())
            {
                FieldInfo[] infos = typeof(WaveFileHeader).GetFields();
                foreach (FieldInfo info in infos)
                {
                    byte[] ba = BitConverter.GetBytes(Convert.ToUInt32(info.GetValue(wfh)));
                    stream.Write(ba, 0, Marshal.SizeOf(info.FieldType));
                }
                stream.Write(wave, 0, wave.Length);

                stream.Seek(0, SeekOrigin.Begin);
                var player = new SoundPlayer(stream);
                player.Play();
            }
        }
    }
}

別の方法

Form1.cs
using System;
using System.IO;
using System.Media;
using System.Text;
using System.Windows.Forms;

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

        private void button1_Click(object sender, EventArgs e)
        {
            const uint sampleRate = 44100;  // サンプリング周波数

            // 波形データの生成
            uint wavelen = (uint)(sampleRate * 1.0);
            byte[] wave = new byte[wavelen];

            double t = 0;
            for (uint i = 0; i < wavelen; i++)
            {
                t = (t + 880.0 / sampleRate) % 1;
                wave[i] = (byte)(128 + Math.Sin(2 * Math.PI * t) * (1 - i / (double)wavelen) * 10);
            }

            //using (FileStream st = new FileStream(@"c:\tmp\hoge.wav", FileMode.Create))
            using (MemoryStream st = new MemoryStream())
            {
                // WAVEファイルヘッダ
                WriteStr(st, "RIFF");
                WriteVal(st, 4, wavelen + 36);
                WriteStr(st, "WAVE");
                WriteStr(st, "fmt ");
                WriteVal(st, 4, 16);
                WriteVal(st, 2, 0x0001);         // WAVE_FORMAT_PCM
                WriteVal(st, 2, 1);              // nChannels
                WriteVal(st, 4, sampleRate);     // nSamplesPerSec
                WriteVal(st, 4, sampleRate);     // nAvgBytesPerSec
                WriteVal(st, 2, 1);              // nBlockAlign
                WriteVal(st, 2, 8);              // wBitsPerSample
                WriteStr(st, "data");
                WriteVal(st, 4, wavelen);

                st.Write(wave, 0, wave.Length);

                st.Seek(0, SeekOrigin.Begin);
                SoundPlayer player = new SoundPlayer(st);
                player.Play();
            }
        }

        private void WriteVal(Stream st, int len, uint value)
        {
            byte[] ba = BitConverter.GetBytes(value);
            st.Write(ba, 0, len);
        }

        private void WriteStr(Stream st, string str)
        {
            byte[] ba = Encoding.ASCII.GetBytes(str);
            st.Write(ba, 0, ba.Length);
        }
    }
}
7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?