cscの作法 その184

# 概要
cscの作法、調べてみた。
managed directxやってみた。
directsound、やってみた。
sin波を鳴らしてみた。

# サンプルコード

```
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;
using System.Threading;

namespace Sample
{
	public partial class Form1 : Form {
		private Device m_DX = null;
		private SecondaryBuffer m_DXBuf = null;
		private Notify m_DXNotify = null;
		private int m_BufSize = 0;
		private byte[] m_DataBuf = null;
		private bool m_IsPlay = false;
		private bool m_IsDoing = false;
		private Thread m_Thread = null;
		private AutoResetEvent m_Event = null;
		private int m_WritePos = 0;
		private bool m_WaveEnd = false;
		private int m_EndDelay = 0;
		delegate void Delegate_Stop_WaveSound();
		private System.Guid dev_guid;
		public Form1() {
			this.Text = "DirectSound";
			this.Load += new EventHandler(this.Form1_Load);
			Button btn1 = new Button();
			btn1.Location = new Point(140, 40);
			btn1.Size = new Size(80, 20);
			btn1.Text = "START";
			btn1.Click += btn1_Click;
			Controls.Add(btn1);
			Button btn2 = new Button();
			btn2.Location = new Point(140, 110);
			btn2.Size = new Size(80, 20);
			btn2.Text = "STOP";
			btn2.Click += btn2_Click;
			Controls.Add(btn2);
			Console.WriteLine("ok0");
		}
		private void Form1_Load(object sender, EventArgs e) {
			DevicesCollection DsEnum = new DevicesCollection();
			DeviceInformation info;
			int i;
			for(i = 0; i < DsEnum.Count; i++)
			{
				info = DsEnum[i];
				if (info.DriverGuid != System.Guid.Empty && info.Description != "")
				{
					Console.WriteLine(info.Description);
					dev_guid = info.DriverGuid;
					Console.WriteLine(info.DriverGuid);
				}
			}
			Console.WriteLine("ok1");
		}
		private void btn1_Click(object sender, EventArgs e) {
			Play_WaveSound();
			Console.WriteLine("start");
			Volume_Control();
		}
		private void btn2_Click(object sender, EventArgs e) {
			Stop_WaveSound();
			Console.WriteLine("stop");
		}
		private bool OpenSoundOutDevice(System.Guid dev_guid) {
			try 
			{
				m_DX = new Device(dev_guid);
				Console.WriteLine(dev_guid);
				m_DX.SetCooperativeLevel(this, CooperativeLevel.Priority);
				BufferDescription desc = new BufferDescription();
				WaveFormat wf = new WaveFormat();
				wf.FormatTag = WaveFormatTag.Pcm;
				wf.SamplesPerSecond = 44100;
				wf.BitsPerSample = 16;
				wf.Channels = 1;
				wf.BlockAlign = (short)(wf.Channels * wf.BitsPerSample / 8);
				wf.AverageBytesPerSecond = wf.SamplesPerSecond * wf.BlockAlign;
				desc.Format = wf;
				desc.BufferBytes = wf.AverageBytesPerSecond / 4;
				desc.Flags = BufferDescriptionFlags.GlobalFocus | BufferDescriptionFlags.ControlPositionNotify | BufferDescriptionFlags.ControlVolume | BufferDescriptionFlags.ControlPan;
				m_DXBuf = new SecondaryBuffer(desc, m_DX);
				desc = null;
				BufferCaps caps;
				caps = m_DXBuf.Caps;
				m_BufSize = caps.BufferBytes;
				Console.WriteLine(m_BufSize);
				if (m_Thread == null)
				{
					m_Thread = new Thread(new System.Threading.ThreadStart(OutputEventTask));
					m_Event = new AutoResetEvent(false);
				}
				m_DXNotify = new Notify(m_DXBuf);
				BufferPositionNotify[] psa = new BufferPositionNotify[2];
				psa[0].EventNotifyHandle = m_Event.Handle;
				psa[0].Offset = (m_BufSize / 2) - 1;
				psa[1].EventNotifyHandle = m_Event.Handle;
				psa[1].Offset = m_BufSize - 1;
				m_DXNotify.SetNotificationPositions(psa, psa.Length);
				m_IsDoing = true;
				m_Thread.Start();
				Console.WriteLine("ok4");
				return true;
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "オープン", MessageBoxButtons.OK);
				CloseSoundOutDevice();
				return false;
			}
		}
		private void CloseSoundOutDevice() {
			m_IsPlay = false;
			m_IsDoing = false;
			if (m_DXBuf != null)
			{
				m_DXBuf.Stop();
			}
			if (m_Thread != null)
			{
				m_Event.Set();
				Thread.Sleep(500);
			}
			m_Event = null;
			m_Thread = null;
			if (m_DXNotify != null)
			{
				m_DXNotify.Dispose();
			}
			m_DXNotify = null;
			if (m_DXBuf != null)
			{
				m_DXBuf.Dispose();
			}
			m_DXBuf = null;
			if (m_DX != null)
			{
				m_DX.Dispose();
			}
			m_DX = null;
		}
		private void OutputEventTask() {
			m_WaveEnd = false;
			m_EndDelay = 3;
			while(m_IsDoing == true)
			{
				m_Event.WaitOne();
				if (m_IsPlay == true)
				{
					System.Array.Clear(m_DataBuf, 0, m_DataBuf.Length);
					int len = 2048;
					if (len == 0 && m_WaveEnd == false)
					{
						m_WaveEnd = true;
						m_EndDelay = 3;
					}
					double A = 440 * 2 * Math.PI / 44100;
					for (int i = 0; i < 11025; i++)
					{
						 m_DataBuf[i] = (byte)(127 * Math.Sin(i * A));
					}
					m_DXBuf.Write(m_WritePos, m_DataBuf, LockFlag.None);
					m_WritePos = m_WritePos + m_DataBuf.Length;
					if (m_WritePos >= m_BufSize)
					{
						m_WritePos = 0;
						Console.WriteLine(".");
					}
					if (m_WaveEnd == true)
					{
						if (m_EndDelay == 0)
						{
							Invoke(new Delegate_Stop_WaveSound(Stop_WaveSound));
						}
						else
						{
							m_EndDelay = m_EndDelay - 1;
						}
					}
				}
			}
		}
		private void Play_WaveSound() {
			if (m_DX == null)
			{
				if (OpenSoundOutDevice(dev_guid) == false)
				{
					return;
				}
				m_DataBuf = null;
				m_DataBuf = new Byte[m_BufSize / 2];
				m_DXBuf.SetCurrentPosition(0);
				m_WritePos = 0;
			}
			if (m_DXBuf !=  null)
			{
				m_DXBuf.Play(0, BufferPlayFlags.Looping);
			}
			m_IsPlay = true;
		}
		private void Pause_WaveSound() {
			m_IsPlay = false;
			if (m_DXBuf != null)
			{
				m_DXBuf.Stop();
			}
		}
		private void Stop_WaveSound() {
			m_IsPlay = false;
			CloseSoundOutDevice();
		}
		private void Volume_Control() {
			if (m_DXBuf == null)
			{
				return;
			}
			int range = 10;
			int vol = (int) Volume.Min;
			if (range > 0 && range <= 100)
			{
				vol = (int) (1000.0 * Math.Log10(range / 100.0));
			}
			if (vol < (int) Volume.Min)
				vol = (int) Volume.Min;
			if (vol > (int) Volume.Max)
				vol = (int) Volume.Max;
			m_DXBuf.Volume = vol;
			Console.WriteLine("vol");
		}
		private void Balance_Control() {
			if (m_DXBuf == null)
			{
				return;
			}
			int range = 50;
			int balance = ((50 - range) * ((Pan.Right - Pan.Left) / 2)) / 100;
			m_DXBuf.Pan = balance;
		}
		[STAThread]
		public static void Main() {
			Application.Run(new Form1());
		}
	}
}





```


以上。