高校受験に挑戦してみた

子どもが高校受験を終えました!

地元の公立小学校でのんびり過ごしていましたが、お受験が盛んな地域という事もあり、なんと!学年の半数近くが中学受験をして中高一貫校へ進学しました。 一方でうちの子どもは小学生の頃は、ピアノ、水泳、英会話、野球などをやっており、とくに成績もよくなかった事から中学受験はしませんでした。しかし高校受験は避けられない事から、中学1年から塾に通いはじめました。

自分は国立学院予備校(現ena)で高校受験しましたが、うちの近くにはなかったので難関校受験の実績があるSAPIXにしました。(あとで分かったのは、早稲田アカデミーの方が実績はあるみたいです)

中学1ー2年の頃は部活が忙しい事もあり塾に通うのがせいいっぱいで、最初は5教科習っていたものも公立はあきらめて3教科にしぼる事になりました。またSAPIX偏差値は30-40台で、学校の成績もほぼオール3でした。 中学2年の終わり頃に塾の先生との面談で、宿題をきちんとやっていないとお叱りを受けました。自分がテキストを確認したところまっ白なページが多く、このままではまずいと自宅で2年生のテキストをすべて解くようにしました。さいわいにも国語は成績が悪くなかったため、数学と英語のテキストだけを復習していきました。 中学3年になると部活も引退し、自宅で復習していた2年生のテキストも終わったことから、偏差値が40-50台に上がってきました。

実力を考えて志望校をMARCH/日東駒専とし、すべり止めに1つ私立を併願優遇で受験する事にしました。(SAPIXの偏差値は世間一般マイナス20くらい)

中学3年の冬は追い込みです。志望校の過去問を中心に勉強する事で本番に備えます。いろいろありましたが結果すべての受験した高校で合格する事ができました!

高校受験を終えた感想としては、実績のある塾できちんとテキストを理解して、実力にあった高校の過去問対策をして受験すれば、結果につながると思いました。部活との両立はつらく塾の学費は高いですが、途中経過が今ひとつだったとしても続ける事が大事だと実感しました。

ちょっとだけDirectX11その2

表題の書籍のサンプルプログラムをSharpDXで書いてみる。

f:id:tanam:20210206092224p:plain

using System;
using SharpDX;
using SharpDX.D3DCompiler;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Windows;
using Buffer = SharpDX.Direct3D11.Buffer;
using Device = SharpDX.Direct3D11.Device;

namespace Sankaku
{
    /// <summary>
    ///   SharpDX port of SharpDX-MiniTri Direct3D 11 Sample
    /// </summary>
    internal static class Program
    {
        [STAThread]
        private static void Main()
        {
            var form = new RenderForm("SharpDX - Direct3D 11 サンプル Sankaku01");

            // SwapChain description
            var desc = new SwapChainDescription()
            {
                BufferCount = 1,
                ModeDescription =
                                   new ModeDescription(640, 480,
                                                       new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed = true,
                OutputHandle = form.Handle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect = SwapEffect.Discard,
                Usage = Usage.RenderTargetOutput
            };

            // Create Device and SwapChain
            Device device;
            SwapChain swapChain;
            Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain);
            var context = device.ImmediateContext;

            // Ignore all windows events
//            var factory = swapChain.GetParent<Factory>();
//            factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);

            // New RenderTargetView from the backbuffer
            var backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
            var renderView = new RenderTargetView(device, backBuffer);

            // Compile Vertex and Pixel shaders
            var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniTri.fx", "VS", "vs_4_0", ShaderFlags.None, EffectFlags.None);
            var vertexShader = new VertexShader(device, vertexShaderByteCode);

            var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniTri.fx", "PS", "ps_4_0", ShaderFlags.None, EffectFlags.None);
            var pixelShader = new PixelShader(device, pixelShaderByteCode);

            // Layout from VertexShader input signature
            var layout = new InputLayout(
                device,
                ShaderSignature.GetInputSignature(vertexShaderByteCode),
                new[]
                    {
                        new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                        new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
                    });

            // Instantiate Vertex buiffer from vertex data
            //            var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[]
            //                                  {
            //                                      new Vector4(0.0f, 0.5f, 0.5f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
            //                                      new Vector4(0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
            //                                      new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)
            //                                  });

            var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[]
                                  {
                                      new Vector4(0.0f, 1.5f, 0.5f, 2.0f), new Vector4(1.0f, 1.0f, 1.0f, 2.0f),
                                      new Vector4(1.0f, -1.0f, 0.5f, 2.0f), new Vector4(1.0f, 1.0f, 1.0f, 2.0f),
                                      new Vector4(-1.0f, -1.0f, 0.5f, 2.0f), new Vector4(1.0f, 1.0f, 1.0f, 2.0f)
                                  });
            
            // Prepare All the stages
            context.InputAssembler.InputLayout = layout;
            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, 32, 0));
            context.VertexShader.Set(vertexShader);
            context.Rasterizer.SetViewport(new Viewport(0, 0, 640, 480, 0.0f, 1.0f));
            context.PixelShader.Set(pixelShader);
            context.OutputMerger.SetTargets(renderView);

            // Main loop
            RenderLoop.Run(form, () =>
            {
                context.ClearRenderTargetView(renderView, new Color(0.0f, 0.5f, 0.7f, 1.0f));
                context.Draw(3, 0);
                swapChain.Present(0, PresentFlags.None);
            });

            // Release all resources
            vertexShaderByteCode.Dispose();
            vertexShader.Dispose();
            pixelShaderByteCode.Dispose();
            pixelShader.Dispose();
            vertices.Dispose();
            layout.Dispose();
            renderView.Dispose();
            backBuffer.Dispose();
            context.ClearState();
            context.Flush();
            device.Dispose();
            context.Dispose();
            swapChain.Dispose();
//            factory.Dispose();
        }
    }
}

第二種電気工事士の資格に挑戦してみる その5

ついに第二種電気工事士の資格取得しました!

さっそく免状交付のために、神奈川県電気工事工業組合本部事務局に行ってきました。

  • 受験用写真 800円
  • 免許用写真 800円
  • 住民票 300円
  • 神奈川県収入証紙 5300円

ちょっとだけDirectX11

表題の書籍でDirectX11の勉強をはじめる。

https://www.kohgakusha.co.jp/books/detail/978-4-7775-1501-1

ひっかかったのはDXSDK_Jun10のサンプルをビルドする必要があると言う事。

C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\C++\Effects11

ここで作成されるEffects11.libをリネームして配置する必要がありました。

C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\d3dx11effect.h
C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86\d3dx11effects.lib

サンプルプログラムをSharpDXで書いてみました。

using System;
using System.Windows.Forms;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.DXGI;
using SharpDX.Windows;
using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
using AlphaMode = SharpDX.Direct2D1.AlphaMode;
using Factory = SharpDX.Direct2D1.Factory;

namespace HelloApp
{

    /// <summary>
    /// Shows how to use DirectWrite to render simple text.
    /// Port of DirectWrite sample SimpleHelloWorld from Windows 7 SDK samples
    /// http://msdn.microsoft.com/en-us/library/dd742738%28v=VS.85%29.aspx
    /// </summary>
    public class Program
    {
        private FormWindowState _currentFormWindowState;
        private Form _form;
        public Factory Factory2D { get; private set; }
        public SharpDX.DirectWrite.Factory FactoryDWrite { get; private set; }
        public WindowRenderTarget RenderTarget2D { get; private set; }
        public SolidColorBrush SceneColorBrush { get; private set; }
        public TextFormat TextFormat { get; private set; }
        public RectangleF ClientRectangle { get; private set; }
        protected IntPtr DisplayHandle
        {
            get
            {
                return _form.Handle;
            }
        }
        protected void Initialize()
        {
            Factory2D = new SharpDX.Direct2D1.Factory();
            FactoryDWrite = new SharpDX.DirectWrite.Factory();
            HwndRenderTargetProperties properties = new HwndRenderTargetProperties();
            properties.Hwnd = DisplayHandle;
            properties.PixelSize = new SharpDX.Size2(640, 480);
            properties.PresentOptions = PresentOptions.None;
            RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)), properties);
            RenderTarget2D.AntialiasMode = AntialiasMode.PerPrimitive;
            SceneColorBrush = new SolidColorBrush(RenderTarget2D, Color.White);
            TextFormat = new TextFormat(FactoryDWrite, "メイリオ", 50) { TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center };
            RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
            ClientRectangle = new RectangleF(0, 0, 640, 480);
            SceneColorBrush.Color = Color.Black;               
        }
        protected void Draw()
        {
            RenderTarget2D.Clear(Color.White);
            RenderTarget2D.DrawText("Hello, World!", TextFormat, ClientRectangle, SceneColorBrush);
        }

        private void HandleResize(object sender, EventArgs e)
        {
            if (_form.WindowState == FormWindowState.Minimized)
            {
                return;
            }

        }
        protected virtual Form CreateForm()
        {
            return new RenderForm("Direct2D Hello Application")
            {
                ClientSize = new System.Drawing.Size(640, 480)
            };
        }

        public void Run()
        {
            _form = CreateForm();
            Initialize();

            bool isFormClosed = false;
            bool formIsResizing = false;

            _form.Resize += (o, args) =>
            {
                if (_form.WindowState != _currentFormWindowState)
                {
                    HandleResize(o, args);
                }

                _currentFormWindowState = _form.WindowState;
            };

            _form.ResizeBegin += (o, args) => { formIsResizing = true; };
            _form.ResizeEnd += (o, args) =>
            {
                formIsResizing = false;
                HandleResize(o, args);
            };

            _form.Closed += (o, args) => { isFormClosed = true; };

            RenderLoop.Run(_form, () =>
            {
                if (isFormClosed)
                {
                    return;
                }
                RenderTarget2D.BeginDraw();
                Draw();
                RenderTarget2D.EndDraw();
            });
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Program program = new Program();
            program.Run();
        }
    }
}

テーブル筐体でアストロシティミニを遊んでみる

テーブル筐体にアストロシティミニを組み込んでみました。

上記は送料込みの金額です。

USBエンコーダとMDミニ用スーパーコンバーターで、コンパネがアストロシティミニで使える事に気付いてやってみました。

アストロシティミニの仕様で16:9のモニタにHDMI出力していますが、テーブル筐体の場合は視野角が非常に重要ですのでIO-DATAのADSパネルを選びました。

※MAGIC-NSを2580円で購入しましたが、USBエンコーダは認識しませんでした。もちろんPS4コントローラは使えました。

Windows RTでNemu

Visual Studio 2012(VS Express for Desktop)で、ファミコンエミュレータNemuをビルドしていきます。

はじめにダウンロードしたソースコードをビルドすると以下のようなエラーがでます。

エラー	2	ファイル FormMain.resx を処理できませんでした。インターネットまたは制限付きゾーン内にあるか、ファイルに Web のマークが付いているためです。これらのファイルを処理するには、Web のマークを削除してください。

以下を参考に対処します。
https://qiita.com/RollSystems/items/67f3a673f9784193779b

つぎにパッケージマネージャ コンソールからSharpDXをインストールし、DirectSound関連を修正します。Any CPUでビルドすれば、Windows RTでもそのまま動きます!

PM> Install-Package SharpDX.DirectSound -Version 4.2.0

NesApu.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;

//using Microsoft.DirectX;
//using Microsoft.DirectX.DirectSound;
using SharpDX;
using SharpDX.DirectSound;
using SharpDX.Multimedia;

namespace Nemu
{
    /// 
    /// ファミコンサウンドプロセッサ
    /// 
    /// 矩形波 2ch
    /// 三角波 1ch
    /// ノイズ 1ch
    /// 
    /// 
    /// デバイス                     三角波 ノイズ 矩形波
    /// ---------------------------- ------ ------ ------
    /// 三角波生成器                     ○
    /// 線形カウンタ                     ○
    /// プログラマブルタイマ             ○     ○     ○
    /// 長さカウンタ                     ○     ○     ○
    /// 4 bit DA コンバータ              ○     ○     ○
    /// エンベロープディケイユニット            ○     ○
    /// スウィープユニット                             ○
    /// デューティサイクル生成器                       ○
    /// 波長コンバータ                          ○
    /// 乱数生成器                              ○
    /// 
    /// 
    class NesApu
    {
        // TODO 矩形波 1・2 のスウィープについて見直す
        // 矩形波 1 と 2 のスウィープ処理で、まだ実装できてない箇所がある。
        // 増加・減少後の処理で、
        //
        // 1's compliment (NOT) is being used for square wave channel 1
        // 2's compliment (NEG) is being used for square wave channel 2
        //
        // ↑この辺がよく分からない。

        // TODO スペランカーのタイトルの音がならないのを修正
        // ゲーム中のディケイもちょっとおかしい。
        // たぶん、軽くするために ChannelEnable の場合のみの
        // 処理を追加したのが原因だと思う。
        // 作ってる途中は鳴ってた

        //-----------------------------------------------------------

        /// 
        /// 44.1 KHz で出力する場合の 1 Hz ごとの
        /// クロック数
        /// CPU クロック / 44100 = 40.584415584415584415582766439909
        /// 
        const double AdditionLimit44 = 40.584415584415584415582766439909;

        /// 
        /// 1 / 4 フレーム分のクロック数
        /// 
        const double AdditionQuarterFrame = 7457.3863636363636363633333333333;

        /// 
        /// 1 / 2 フレーム分のクロック数
        /// 
        //const double AdditionHalfFrame = 14914.772727272727272727272727273;


        /// 
        /// 長さカウンタのテーブル (32 個)
        /// 
        /// 長さカウンタの設定用レジスタに渡される値は、
        /// このテーブルのインデックス値になる。
        /// このテーブルはルックアップテーブルとして使われる。
        /// 
        /// 
        static byte[] LengthCounterTable = {
            // 1     2     3     4     5     6     7     8
            0x05, 0x7F, 0x0A, 0x01, 0x14, 0x02, 0x28, 0x03,
            // 9    10    11    12    13    14    15    16
            0x50, 0x04, 0x1E, 0x05, 0x07, 0x06, 0x0E, 0x07,
            //17    18    19    20    21    22    23    24
            0x06, 0x08, 0x0C, 0x09, 0x18, 0x0A, 0x30, 0x0B,
            //25    26    27    28    29    30    31    32
            0x60, 0x0C, 0x24, 0x0D, 0x08, 0x0E, 0x10, 0x0F
        };

        /// 
        /// ノイズチャネルのプログラマブルタイマのテーブル
        /// 
        /// ノイズチャネルの設定用レジスタ (0x400E) で渡される
        /// 値は、このテーブルのインデックス値になる。
        /// 上のテーブルと同様に、このテーブルは
        /// ルックアップテーブルとして使われる。
        /// 
        /// 
        static int[] NoiseWavelengthTable = {
            //  0      1      2      3      4      5      6      7
            0x002, 0x004, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 
            //  8      9      A      B      C      D      E      F
            0x065, 0x07F, 0x0BE, 0x0FE, 0x17D, 0x1FC, 0x3F9, 0x7F2
        };

        //-----------------------------------------------------------

        /// 
        /// システムリセット時の最初の初期化処理が終わったかどうか
        /// 
        /// システムリセットから最初の 2048 クロックは処理を停止する
        /// 
        /// 
        static bool SoundFirstInitFlag = false;

        /// 
        /// システムリセット時の最初の初期化処理用カウンタ
        /// 
        static int SoundFirstInitCounter = 0;

        //-----------------------------------------------------------

        /// 
        /// 矩形波チャネル 1 有効フラグ
        /// (0x4015で設定する)
        /// 
        static bool SquareChannel1Enable = false;

        /// 
        /// 矩形波チャネル 2 有効フラグ
        /// (0x4015で設定する)
        /// 
        static bool SquareChannel2Enable = false;

        /// 
        /// 三角波チャネル 有効フラグ
        /// (0x4015で設定する)
        /// 
        static bool TriangleChannelEnable = false;

        /// 
        /// ノイズチャネル 有効フラグ
        /// (0x4015で設定する)
        /// 
        static bool NoiseChannelEnable = false;

        /// 
        /// DMC チャネル 有効フラグ
        /// (0x4008で設定する)
        /// 
        static bool DMCChannelEnable = false;

        //-----------------------------------------------------------

        /// 
        /// 矩形波 1 チャネル 長さカウンタ無効フラグ
        /// (0x4000で設定する)
        /// 
        static bool Square1LengthCounterDisable = true;

        /// 
        /// 矩形波 1 のデューティサイクルタイプ
        /// (0x4001で設定する)
        /// 
        /// Value positive/negative
        /// ----- -----
        /// 00	   2/14
        /// 01	   4/12
        /// 10	   8/ 8
        /// 11	  12/ 4
        /// 
        /// 
        static int Square1DutyCycleType = 0;

        /// 
        /// 矩形波 1 のデューティサイクルカウンタ
        /// Square1DutyCycleType とセットで使う
        /// 
        /// 0 ~ 15 の値を取る
        /// 
        /// 
        static int Square1DutyCycleCounter = 0;

        /// 
        /// 矩形波 1 用プログラマブルタイマ (11 bit長)
        /// 
        static int Square1ProgrammableTimer = 0;

        /// 
        /// 矩形波 1 長さカウンタ (7 bit長)
        /// 
        static int Square1LengthCounter = 0;

        /// 
        /// 矩形波 1 ディケイカウンタ
        /// 
        static int Square1DecayCounter = 0;

        /// 
        /// 矩形波 1 のボリューム値もしくはディケイレート
        /// (0x4000で設定する)
        /// 
        static int Square1VolumeAndDecayRate = 0;

        /// 
        /// ディケイがかかったボリューム値
        /// 
        static int Square1DecayedVolume = 0;

        /// 
        /// 矩形波 1 ディケイ無効
        /// (0x4000で設定する)
        /// 
        static bool Square1DecayDisable = true;

        /// 
        /// 矩形波 1 スウィープユニット有効
        /// (0x4001で設定する)
        /// 
        static bool Square1SweepEnable = false;

        /// 
        /// 矩形波 1 スウィープユニット更新レート
        /// (0x4001で設定する)
        /// 
        static int Square1SweepUpdateRate = 0;

        /// 
        /// 矩形波 1 スウィープ方向
        /// (0x4001で設定する)
        /// 0 か 1 の値を取る
        /// 
        /// 1 : 減少
        /// 0 : 増加
        /// 
        /// 
        static int Square1SweepDirection = 0;

        /// 
        /// 矩形波 1 スウィープ右シフト量
        /// (0x4001で設定する)
        /// 
        static int Square1SweepShiftAmount = 0;

        /// 
        /// 矩形波 1 のスウィープ実行開始カウンタ
        /// 
        static int Square1SweepCounter = 0;

        /// 
        /// 矩形波 1 のスウィープ動作時に特定の条件が揃ったら
        /// 矩形波 1 チャネルの音を停止する
        /// 
        static bool Square1SilenceFlag = false;

        //-----------------------------------------------------------

        /// 
        /// 矩形波 2 チャネル 長さカウンタ無効フラグ
        /// (0x4004で設定する)
        /// 
        static bool Square2LengthCounterDisable = true;

        /// 
        /// 矩形波 2 のデューティサイクルタイプ
        /// (0x4004で設定する)
        /// 
        /// Value positive/negative
        /// ----- -----
        /// 00	   2/14
        /// 01	   4/12
        /// 10	   8/ 8
        /// 11	  12/ 4
        /// 
        /// 
        static int Square2DutyCycleType = 0;

        /// 
        /// 矩形波 2 のデューティサイクルカウンタ
        /// Square2DutyCycleType とセットで使う
        /// 
        /// 0 ~ 15 の値を取る
        /// 
        /// 
        static int Square2DutyCycleCounter = 0;

        /// 
        /// 矩形波 2 用プログラマブルタイマ (11 bit長)
        /// 
        static int Square2ProgrammableTimer = 0;

        /// 
        /// 矩形波 2 長さカウンタ (7 bit長)
        /// 
        static int Square2LengthCounter = 0;

        /// 
        /// 矩形波 2 ディケイカウンタ
        /// 
        static int Square2DecayCounter = 0;

        /// 
        /// 矩形波 2 のボリューム値もしくはディケイレート
        /// (0x4004で設定する)
        /// 
        static int Square2VolumeAndDecayRate = 0;

        /// 
        /// ディケイがかかったボリューム値
        /// 
        static int Square2DecayedVolume = 0;

        /// 
        /// 矩形波 2 ディケイ無効
        /// (0x4004で設定する)
        /// 
        static bool Square2DecayDisable = true;

        /// 
        /// 矩形波 2 スウィープユニット有効
        /// (0x4005で設定する)
        /// 
        static bool Square2SweepEnable = false;

        /// 
        /// 矩形波 2 スウィープユニット更新レート
        /// (0x4005で設定する)
        /// 
        static int Square2SweepUpdateRate = 0;

        /// 
        /// 矩形波 2 スウィープ方向
        /// (0x4005で設定する)
        /// 0 か 1 の値を取る
        /// 
        /// 1 : 減少
        /// 0 : 増加
        /// 
        /// 
        static int Square2SweepDirection = 0;

        /// 
        /// 矩形波 2 スウィープ右シフト量
        /// (0x4005で設定する)
        /// 
        static int Square2SweepShiftAmount = 0;

        /// 
        /// 矩形波 2 のスウィープ実行開始カウンタ
        /// 
        static int Square2SweepCounter = 0;

        /// 
        /// 矩形波 2 のスウィープ動作時に特定の条件が揃ったら
        /// 矩形波 2 チャネルの音を停止する
        /// 
        static bool Square2SilenceFlag = false;

        //-----------------------------------------------------------

        /// 
        /// 三角波チャネル 長さカウンタ無効フラグ
        /// (0x4015で設定する)
        /// 
        static bool TriangleLengthCounterDisable = true;

        /// 
        /// 三角波チャネルのロードモードが ON の時 True
        /// 
        static bool TriangleLoadModeFlag = false;

        /// 
        /// 三角波生成カウンタ (5 bit長)
        /// 
        static int TriangleStepCounter = 0;

        /// 
        /// 三角波用 線形カウンタ (7 bit長)
        /// 
        static int LinearCounter = 0;

        /// 
        /// 三角波プログラマブルタイマー (11 bit長)
        /// 
        static int TriangleProgrammableTimer = 0;

        /// 
        /// 三角波長さカウンタ (7 bit長)
        /// 
        static int TriangleLengthCounter = 0;

        //-----------------------------------------------------------

        /// 
        /// ノイズチャネル シフトレジスタ
        /// リセット時、 1 に初期化される
        /// 
        static int NoiseShiftRegister = 1;

        /// 
        /// ノイズシフト実行フラグ
        /// 
        /// ノイズシフト動作は、乱数生成器が
        /// 2 回呼び出されるごとに 1 回実行されるので、
        /// その状態を保存するためのフラグ
        /// 
        /// 
        static bool NoiseShiftFlag = false;

        /// 
        /// ノイズチャネル 長さカウンタ無効フラグ
        /// (0x400Dで設定する)
        /// 
        static bool NoiseLengthCounterDisable = true;

        /// 
        /// ノイズ 用プログラマブルタイマ (11 bit長)
        /// 
        static int NoiseProgrammableTimer = 0;

        /// 
        /// ノイズ 長さカウンタ (7 bit長)
        /// 
        static int NoiseLengthCounter = 0;

        /// 
        /// ノイズ ディケイカウンタ
        /// 
        static int NoiseDecayCounter = 0;

        /// 
        /// ノイズ のボリューム値もしくはディケイレート
        /// (0x400Cで設定する)
        /// 
        static int NoiseVolumeAndDecayRate = 0;

        /// 
        /// ノイズ のディケイがかかったボリューム値
        /// 
        static int NoiseDecayedVolume = 0;

        /// 
        /// ノイズ ディケイ無効
        /// (0x400Cで設定する)
        /// 
        static bool NoiseDecayDisable = true;

        /// 
        /// ノイズ 乱数生成モード
        /// (0x400Eで設定する)
        /// 
        /// 0 : 32767 ビット長の乱数
        /// 1 : 93 ビット長の乱数
        /// (同じものが出てくるまでのサイクル)
        /// 
        /// 
        static int NoiseRandomGeneratorMode = 0;

        //-----------------------------------------------------------

        /// 
        /// 1 / 4 フレームをカウントするカウンタ
        /// 
        static double ClockQuarterFrame = 0;

        /// 
        /// 1 / 2 フレーム長を計算するためのフラグ
        /// 1 / 4 フレームのカウンタから計算するため、
        /// 2 回に 1 回カウントするために必要
        /// 
        static bool HalfFrameFlag = false;

        //-----------------------------------------------------------

        /// 
        /// AdditionLimit に達するまでクロックを足していく
        /// AdditionLimit に達したら、1Hz 分の波形をバッファに格納する
        /// 
        static double ClockAddition = 0;

        /// 
        /// 矩形波 1 の音量を 1 フレームの長さに達するまで足していく
        /// 
        static int Square1Addition = 0;

        /// 
        /// 矩形波 2 の音量を 1 フレームの長さに達するまで足していく
        /// 
        static int Square2Addition = 0;

        /// 
        /// 三角波の音量を 1 フレームの長さに達するまで足していく
        /// 
        static int TriangleAddition = 0;

        /// 
        /// ノイズチャネルの音量を 1 フレームの長さに達するまで足していく
        /// 
        static int NoiseAddition = 0;

        /// 
        /// 後で音量の平均値を出すために足し合わせた回数を保存しておく
        /// 
        static int AdditionCount = 0;

        /// 
        /// 1 秒分のリングバッファ
        /// 
        static short[] RingBuffer = new short[44100];

        /// 
        /// リングバッファの現在の参照先
        /// 
        static volatile int RingBufferPointer = 0;

        /// 
        /// リングバッファの現在の再生位置
        /// 
        static volatile int CurrentPosition = 0;

        /// 
        /// スレッド実行中フラグ
        /// 
        static public volatile bool StillRunning = false;

        //-----------------------------------------------------------

        //static Semaphore semaphore;

        /// 
        /// DirectSound デバイス
        /// 
//        static Device device = null;
        static DirectSound device = null;

        /// 
        /// セカンダリバッファ
        /// 
//        static SecondaryBuffer secondaryBuffer = null;
        static SecondarySoundBuffer secondaryBuffer = null;

        /// 
        /// セカンダリバッファの種類設定
        /// 
//        static BufferDescription bufferDescription = null;
        static SoundBufferDescription bufferDescription = null;

        /// 
        /// リングバッファの読み込み位置通知イベント用
        /// 
        static AutoResetEvent[] autoResetEvent = null;

        /// 
        /// リングバッファの読み込み位置通知イベント用
        /// 
//        static BufferPositionNotify[] bufferPositionNotify = null;
        static NotificationPosition[] bufferPositionNotify = null;
  
        /// 
        /// リングバッファの読み込み位置通知イベント用
        /// 
//        static Notify notify = null;

        /// 
        /// サウンドを鳴らすスレッド
        /// イベント待ちループを回す
        /// 
        static Thread thread = null;

        /// 
        /// 
        /// 
        static FileStream fs = null;

        /// 
        /// 
        /// 
        //static string filename = "../../Sample.wav";

        /// 
        /// バッファサイズ
        /// 
        const int buffersize = 44100;

        //-----------------------------------------------------------

        /// 
        /// メンバ変数の初期化
        /// 
        public static void InitMemberVariable()
        {
            StillRunning = false;

            SoundFirstInitFlag = false;
            SoundFirstInitCounter = 0;

            ClockQuarterFrame = 0;
            HalfFrameFlag = false;
            RingBufferPointer = 0;
            CurrentPosition = 0;

            // チャネル有効フラグ
            SquareChannel1Enable = false;
            SquareChannel2Enable = false;
            TriangleChannelEnable = false;
            NoiseChannelEnable = false;
            DMCChannelEnable = false;

            // 矩形波 1
            Square1LengthCounterDisable = true;
            Square1DutyCycleType = 0;
            Square1DutyCycleCounter = 0;
            Square1ProgrammableTimer = 0;
            Square1LengthCounter = 0;
            Square1DecayCounter = 0;
            Square1VolumeAndDecayRate = 0;
            Square1DecayedVolume = 0;
            Square1DecayDisable = true;
            Square1SweepEnable = false;
            Square1SweepUpdateRate = 0;
            Square1SweepDirection = 0;
            Square1SweepShiftAmount = 0;
            Square1SweepCounter = 0;
            Square1SilenceFlag = false;

            // 矩形波 2
            Square2LengthCounterDisable = true;
            Square2DutyCycleType = 0;
            Square2DutyCycleCounter = 0;
            Square2ProgrammableTimer = 0;
            Square2LengthCounter = 0;
            Square2DecayCounter = 0;
            Square2VolumeAndDecayRate = 0;
            Square2DecayedVolume = 0;
            Square2DecayDisable = true;
            Square2SweepEnable = false;
            Square2SweepUpdateRate = 0;
            Square2SweepDirection = 0;
            Square2SweepShiftAmount = 0;
            Square2SweepCounter = 0;
            Square2SilenceFlag = false;

            // 三角波
            TriangleLengthCounterDisable = true;
            TriangleLoadModeFlag = false;
            TriangleStepCounter = 0;
            LinearCounter = 0;
            TriangleProgrammableTimer = 0;
            TriangleLengthCounter = 0;

            // ノイズチャネル
            NoiseShiftRegister = 1;
            NoiseShiftFlag = false;
            NoiseLengthCounterDisable = true;
            NoiseProgrammableTimer = 0;
            NoiseLengthCounter = 0;
            NoiseDecayCounter = 0;
            NoiseVolumeAndDecayRate = 0;
            NoiseDecayedVolume = 0;
            NoiseDecayDisable = true;
            NoiseRandomGeneratorMode = 0;

            // 音量の積算用
            Square1Addition = 0;
            Square2Addition = 0;
            TriangleAddition = 0;
            AdditionCount = 0;
            ClockAddition = 0;
        }

        /// 
        /// DirectSoundの初期化
        /// 
        public static void Init()
        {
            InitMemberVariable();

            try
            {
                //semaphore = new Semaphore(0, 1);

                // デバイスの作成
//                device = new Device();
                device = new DirectSound();

                // 協調レベルの設定
//                device.SetCooperativeLevel(FormManager.formMain, CooperativeLevel.Priority);
                device.SetCooperativeLevel(FormManager.formMain.Handle, CooperativeLevel.Priority);

                // リングバッファ を無音に設定
                //for (int i = 0; i < RingBuffer.Length; i++)
                //{
                //    RingBuffer[i] = 128;
                //}


//                bufferDescription = new BufferDescription(GetFormat());
//                bufferDescription.Flags = BufferDescriptionFlags.ControlPositionNotify
//                                       | BufferDescriptionFlags.ControlVolume
//                                       | BufferDescriptionFlags.LocateInSoftware;
//                bufferDescription.BufferBytes = (44100 * 2) / 20 * 5;

                WaveFormat waveFormat = new WaveFormat();
                bufferDescription = new SoundBufferDescription();
                bufferDescription.Format = waveFormat;
                bufferDescription.Flags = BufferFlags.ControlPositionNotify
                       | BufferFlags.ControlVolume
                       | BufferFlags.Software;
                bufferDescription.BufferBytes = (44100 * 2) / 20 * 5;

                autoResetEvent = new AutoResetEvent[6];
                
                for (int i = 0; i < 5; i++)
                {
                    autoResetEvent[i] = new AutoResetEvent(true);  //中間地点通知用
                };
                //autoResetEvent[0] = new AutoResetEvent(false);  //再生終了通知用
                autoResetEvent[5] = new AutoResetEvent(false);  //再生終了通知用

                // セカンダリバッファにファイルからバッファをロードします
//                secondaryBuffer = new SecondaryBuffer(bufferDescription, device);
                secondaryBuffer = new SecondarySoundBuffer(device, bufferDescription);
                //secondaryBuffer.Volume = 1000;
                
//                notify = new Notify(secondaryBuffer);

//                bufferPositionNotify = new BufferPositionNotify[5];

//                for (int i = 0; i < 5; i++)
//                {
//                    bufferPositionNotify[i].Offset = ((44100 * 2) / 20 * i);
//                    bufferPositionNotify[i].EventNotifyHandle = autoResetEvent[i].Handle;
//                }

//                notify.SetNotificationPositions(bufferPositionNotify);

                var list = new List();
                for (int i = 0; i < 4; i++)
                {
                    list.Add(new NotificationPosition()
                    {
                        WaitHandle = autoResetEvent[i],
                        Offset = i * (44100 * 2) / 20 + 1,
                    });
                }
                list.Add(new NotificationPosition()
                {
                    Offset = 4 * (44100 * 2) / 20 - 1,
                    WaitHandle = autoResetEvent[4]
                });
                bufferPositionNotify = list.ToArray();
                secondaryBuffer.SetNotificationPositions(bufferPositionNotify);

                // セカンダリバッファを無音にする
                short[] buf = new short[44100 / 20 * 5];
                Array.Copy(RingBuffer, buf, 44100 / 20 * 5);
//                secondaryBuffer.Write(0, buf, LockFlag.EntireBuffer);
                secondaryBuffer.Write(buf, 0, LockFlags.EntireBuffer);
                secondaryBuffer.Volume = -10000;

                thread = new Thread(new ThreadStart(StreamLoadThread));
                thread.Priority = ThreadPriority.Normal;
                thread.Start();

//                secondaryBuffer.Play(0, BufferPlayFlags.Looping);
                secondaryBuffer.Play(0, PlayFlags.Looping);
                secondaryBuffer.Volume = -1000;
            }
            catch (Exception)
            {
                // 失敗
                Logger.Write("NesApu エラー : DirectSoundの初期化に失敗しました。");
            }

            //semaphore.Release(1);
        }

        /// 
        /// バッファ読み込み位置イベント待ちループ
        /// (別スレッドで起動)
        /// 
        static void StreamLoadThread()
        {
            //int size = buffersize / 2;
            short[] buf = new short[44100 / 20];
            short[] nullbuf = new short[44100 / 20];

            for (int i = 0; i < nullbuf.Length; i++)
                nullbuf[i] = 128;
            
            StillRunning = true;
            //Console.WriteLine("*** StreamLoadThread start");

            while (true)
            {
                int eventNumber;
                int pos = 0;
                //int rPointer;

                eventNumber = AutoResetEvent.WaitAny(autoResetEvent);
                //Console.WriteLine("Write : {0}, Play {1}, Ev{2}", secondaryBuffer.WritePosition, secondaryBuffer.PlayPosition,eventNumber);

                if (eventNumber == 5)
                {
                    secondaryBuffer.Volume = -10000;
                    secondaryBuffer.Stop();
                    return;
                }

                //pos = 44100 / 60 * (eventNumber);

                //semaphore.WaitOne();

                //if (CurrentPosition > RingBufferPointer)
                //    continue;

                int source;

                source = RingBufferFilled - (44100 / 20);
                if (source < 0)
                    source += 44100;

                Array.Copy(RingBuffer, source, buf, 0, (44100 / 20));

                CurrentPosition += (44100 / 20);
                if (CurrentPosition >= 44100)
                {
                    CurrentPosition = 0;
                }
                //semaphore.Release();

                //pos = 44100 / 30 * (eventNumber - 1);
                //if (pos < 0)
                //{
                //    pos = 44100 + pos;
                //}
                switch (eventNumber)
                {
                    case 0:
                        pos = (44100 * 2 / 20) * 4;
                        //if (secondaryBuffer.WritePosition > (44100 / 60) * 2)
                        //    continue;
                        break;
                    case 1:
                        pos = 0;
                        break;
                    case 2:
                        pos = (44100 * 2 / 20);
                        break;
                    case 3:
                        pos = (44100 * 2 / 20) * 2;
                        break;
                    case 4:
                        pos = (44100 * 2 / 20) * 3;
                        break;
                }

                //try
                //{
//                secondaryBuffer.Write(pos, buf, LockFlag.None);
                secondaryBuffer.Write(buf, pos, LockFlags.None);
                //Console.WriteLine("Write : {0}, Play {1}, Ev{2}", secondaryBuffer.WritePosition, secondaryBuffer.PlayPosition, eventNumber);

                    //Console.WriteLine("Write : {0}, Play {1}", secondaryBuffer.WritePosition, secondaryBuffer.PlayPosition);
                //}
                //catch (Exception)
                //{
                //    return;
                //}


                /*switch (eventNumber)
                {
                    case 0:
                        secondaryBuffer.Write(0, buf, LockFlag.None);
                        break;
                    case 1:
                        secondaryBuffer.Write(size, buf, LockFlag.None);
                        break;
                    case 2:
                        Console.WriteLine("Sound Notify");
                        return;
                }*/
            }
        }

        /// 
        /// バッファ読み込み位置イベント待ちループを停止
        /// 
        static public void StopStreamLoadThread()
        {
            if (thread != null)
            {
                //if (thread.ThreadState == ThreadState.Running)
                //{
                    //thread.Abort();
                //}
                autoResetEvent[5].Set();
                thread.Join();
                StillRunning = false;
            }
            
            if (secondaryBuffer != null)
            {
                secondaryBuffer.Stop();
                secondaryBuffer.Dispose();
            }

            if (autoResetEvent != null)
            {
                for (int i = 0; i < 5; i++)
                    autoResetEvent[i].Close();
            }
        }

        /// 
        /// WaveFormatを作って返す
        /// 
        ///
        /// 
/*        static WaveFormat GetFormat()
        {
            WaveFormat waveFormat = new WaveFormat();
            //byte[] buf = new byte[36];
            //fs.Read(buf, 0, 36);

            // RIFFなWAVE以外の場合はWAVEにデコードした際のフォーマットを作る。
            // (WAV再生するだけならいらないので省略)
            //if (buf[0] == (byte)'R' && buf[1] == (byte)'I' && buf[2] == (byte)'F' && buf[3] == (byte)'F'
            //    && buf[8] == (byte)'W' && buf[9] == (byte)'A' && buf[10] == (byte)'V' && buf[11] == (byte)'E')
            //{

            waveFormat.FormatTag = WaveFormatTag.Pcm;
            waveFormat.Channels = 1;
            waveFormat.SamplesPerSecond = 44100;
            waveFormat.BitsPerSample = 16;
            waveFormat.BlockAlign = 2;
            waveFormat.AverageBytesPerSecond = waveFormat.BlockAlign * waveFormat.SamplesPerSecond;
            //}
            //else{
            //}
            //fs.Seek(0, System.IO.SeekOrigin.Begin);
            return waveFormat;
        } */

        //-----------------------------------------------------------

        /// 
        /// 矩形波 1 の設定レジスタ 1 に書き込み (0x4000)
        /// 
        ///
        public static void WriteSquare1ControlRegister1(byte value)
        {
            // [Bit 6-7] デューティサイクルタイプ
            Square1DutyCycleType = value >> 6;

            // [Bit 5] 長さカウンタ無効フラグ
            Square1LengthCounterDisable = (value & 0x20) > 0 ? true : false;
            
            // [Bit 4] ディケイユニット無効フラグ
            Square1DecayDisable = (value & 0x10) > 0 ? true : false;

            // [Bit 0-3] ディケイレート
            Square1VolumeAndDecayRate = value & 0x0F;
        }

        /// 
        /// 矩形波 1 の設定レジスタ 2 に書き込み (0x4001)
        /// 
        ///
        public static void WriteSquare1ControlRegister2(byte value)
        {
            // [Bit 0-2] スウィープ右シフト量
            Square1SweepShiftAmount = value & 0x07;

            // [Bit 3] スウィープ方向
            Square1SweepDirection = (value >> 3) & 0x01;

            // [Bit 4-6] スウィープ更新レート
            Square1SweepUpdateRate = (value >> 4) & 0x07;

            // [Bit 7] スウィープ有効
            Square1SweepEnable = (value & 0x80) > 0 ? true : false;
        }

        /// 
        /// 矩形波 1 のプログラマブルタイマに書き込み (0x4002)
        /// 
        ///
        public static void WriteSquare1ProgrammableTimerRegister(byte value)
        {
            Square1ProgrammableTimer &= 0xF00;
            Square1ProgrammableTimer |= value;
        }

        /// 
        /// 矩形波 1 の長さカウンタレジスタに書き込み (0x4003)
        /// 
        ///
        public static void WriteSquare1LengthCounterRegister(byte value)
        {
            Square1ProgrammableTimer &= 0xFF;
            Square1ProgrammableTimer |= ((value & 0x07) << 8);

            if (SquareChannel1Enable == true)
            {
                Square1LengthCounter = LengthCounterTable[(value >> 3) & 0x1F];
            }

            // ディケイボリュームレベルを最大音量にリセット
            Square1DecayedVolume = 0x0F;
        }

        //-----------------------------------------------------------

        /// 
        /// 矩形波 2 の設定レジスタ 1 に書き込み (0x4004)
        /// 
        ///
        public static void WriteSquare2ControlRegister1(byte value)
        {
            // [Bit 6-7] デューティサイクルタイプ
            Square2DutyCycleType = value >> 6;

            // [Bit 5] 長さカウンタ無効フラグ
            Square2LengthCounterDisable = (value & 0x20) > 0 ? true : false;

            // [Bit 4] ディケイユニット無効フラグ
            Square2DecayDisable = (value & 0x10) > 0 ? true : false;

            // [Bit 0-3] ディケイレート
            Square2VolumeAndDecayRate = value & 0x0F;
        }

        /// 
        /// 矩形波 2 の設定レジスタ 2 に書き込み (0x4005)
        /// 
        ///
        public static void WriteSquare2ControlRegister2(byte value)
        {
            // [Bit 0-2] スウィープ右シフト量
            Square2SweepShiftAmount = value & 0x07;

            // [Bit 3] スウィープ方向
            Square2SweepDirection = (value >> 3) & 0x01;

            // [Bit 4-6] スウィープ更新レート
            Square2SweepUpdateRate = (value >> 4) & 0x07;

            // [Bit 7] スウィープ有効
            Square2SweepEnable = (value & 0x80) > 0 ? true : false;
        }

        /// 
        /// 矩形波 2 のプログラマブルタイマに書き込み (0x4006)
        /// 
        ///
        public static void WriteSquare2ProgrammableTimerRegister(byte value)
        {
            Square2ProgrammableTimer &= 0xF00;
            Square2ProgrammableTimer |= value;
        }

        /// 
        /// 矩形波 2 の長さカウンタレジスタに書き込み (0x4007)
        /// 
        ///
        public static void WriteSquare2LengthCounterRegister(byte value)
        {
            Square2ProgrammableTimer &= 0xFF;
            Square2ProgrammableTimer |= ((value & 0x07) << 8);

            if (SquareChannel2Enable == true)
            {
                Square2LengthCounter = LengthCounterTable[(value >> 3) & 0x1F];
            }

            // ディケイボリュームレベルを最大音量にリセット
            Square2DecayedVolume = 0x0F;
        }

        //-----------------------------------------------------------

        /// 
        /// 三角波の線形カウンタレジスタに書き込み (0x4008)
        /// 
        ///
        public static void WriteTriangleLinearCounterRegister(byte value)
        {
            // [Bit 7] 長さカウンタ無効フラグ
            TriangleLengthCounterDisable = (value & 0x80) > 0 ? true : false;

            // [Bit 0-6] 線形カウンタのカウント値
            // StepLinearCounterで、NesStorage.IO2[0x08]からリロードされるので
            // ここでの処理は無し
        }

        // (0x4009 は使われていない)

        /// 
        /// 三角波プログラマブルタイマレジスタに書き込み (0x400A)
        /// 
        ///
        public static void WriteTriangleProgrammableTimerRegister(byte value)
        {
            // [Bit 0-7] プログラマブルタイマーの下位 8 ビット
            TriangleProgrammableTimer &= 0xF00;
            TriangleProgrammableTimer |= value;
        }

        /// 
        /// 三角波の長さカウンタレジスタに書き込み (0x400B)
        /// 
        ///
        public static void WriteTriangleLengthCounterRegister(byte value)
        {
            // [Bit 0-2] 三角波プログラマブルタイマーの上位 3 ビット
            TriangleProgrammableTimer &= 0xFF;
            TriangleProgrammableTimer |= ((value & 0x07) << 8);

            // [Bit 3-7] 長さカウンタの値をロード
            if (TriangleChannelEnable == true)
            {
                TriangleLengthCounter = LengthCounterTable[(value >> 3) & 0x1F];
            }

            // ロードモード ON
            TriangleLoadModeFlag = true;
        }

        //-----------------------------------------------------------

        /// 
        /// ノイズ の設定レジスタに書き込み (0x400C)
        /// 
        ///
        public static void WriteNoiseControlRegister1(byte value)
        {
            // [Bit 6-7] 使われていない

            // [Bit 5] 長さカウンタ無効フラグ
            NoiseLengthCounterDisable = (value & 0x20) > 0 ? true : false;

            // [Bit 4] ディケイユニット無効フラグ
            NoiseDecayDisable = (value & 0x10) > 0 ? true : false;

            // [Bit 0-3] ディケイレート
            NoiseVolumeAndDecayRate = value & 0x0F;
        }

        // (0x400D は使われていない)

        /// 
        /// ノイズ の設定レジスタ 2 に書き込み (0x400E)
        /// 
        ///
        public static void WriteNoiseControlRegister2(byte value)
        {
            int rate;

            // [Bit 0-3] サンプリングレート
            rate = value & 0x0F;
            NoiseProgrammableTimer = NoiseWavelengthTable[rate];

            // [Bit 4-6] 使われていない

            // [Bit 7] 乱数タイプ
            NoiseRandomGeneratorMode = (value & 0x80) > 0 ? 1 : 0;
        }

        /// 
        /// ノイズ 長さカウンタレジスタに書き込み (0x400F)
        /// 
        ///
        public static void WriteNoiseLengthCounterRegister(byte value)
        {
            // [Bit 0-2] 使われていない

            // [Bit 3-7] 長さカウンタの値をロード
            //if (NoiseChannelEnable == true)
            //{
                NoiseLengthCounter = LengthCounterTable[(value >> 3) & 0x1F];
            //}

            // ディケイボリュームレベルを最大音量にリセット
            NoiseDecayedVolume = 0x0F;
        }

        //-----------------------------------------------------------

        /// 
        /// チャネル有効レジスタに書き込み (0x4015)
        /// 
        ///
        public static void WriteChannelEnableRegister(byte value)
        {
            // [Bit 0] 矩形波チャネル 1
            if ((value & 0x01) > 0)
            {
                SquareChannel1Enable = true;
            }
            else
            {
                SquareChannel1Enable = false;
                Square1LengthCounter = 0;
            }

            // [Bit 1] 矩形波チャネル 2
            if ((value & 0x02) > 0)
            {
                SquareChannel2Enable = true;
            }
            else
            {
                SquareChannel2Enable = false;
                Square2LengthCounter = 0;
            }

            // [Bit 2] 三角波チャネル
            if ((value & 0x04) > 0)
            {
                TriangleChannelEnable = true;
            }
            else
            {
                TriangleChannelEnable = false;
                TriangleLengthCounter = 0;
            }

            // [Bit 3] ノイズチャネル
            if ((value & 0x08) > 0)
            {
                NoiseChannelEnable = true;
            }
            else
            {
                NoiseChannelEnable = false;
                NoiseLengthCounter = 0;
            }

            // [Bit 4] DMC チャネル
            DMCChannelEnable = (value & 0x10) > 0 ? true : false;
        }


        /// 
        /// 長さカウンタステータスレジスタから読み込み (0x4015)
        /// 
        /// 
        public static byte ReadLengthCounterStatusRegister()
        {
            byte status;

            status = 0;

            // 矩形波 1 の状態
            if (Square1LengthCounter != 0)
                status |= 0x01;

            // 矩形波 2 の状態
            if (Square2LengthCounter != 0)
                status |= 0x02;

            // 三角波の状態
            if (TriangleLengthCounter != 0)
                status |= 0x04;

            // ノイズチャネルの状態
            if (NoiseLengthCounter != 0)
                status |= 0x08;

            return status;
        }

        //-----------------------------------------------------------

        /// 
        /// 矩形波 1 のデューティサイクルカウンタ
        /// このメソッドが呼び出されるたびに
        /// 三角波をバッファに格納していく
        /// 
        public static void IncrementSquare1DutyCycleCounter()
        {
            Square1DutyCycleCounter++;

            if (Square1DutyCycleCounter == 16)
                Square1DutyCycleCounter = 0;
        }

        /// 
        /// 矩形波 2 のデューティサイクルカウンタ
        /// このメソッドが呼び出されるたびに
        /// 三角波をバッファに格納していく
        /// 
        public static void IncrementSquare2DutyCycleCounter()
        {
            Square2DutyCycleCounter++;

            if (Square2DutyCycleCounter == 16)
                Square2DutyCycleCounter = 0;
        }

        /// 
        /// 三角波 ステップカウンタ
        /// 
        public static void IncrementTriangleStepCounter()
        {
            if (LinearCounter != 0)
            {
                TriangleStepCounter++;

                // 6 ビット目に達したら 0 クリアする
                if (TriangleStepCounter >= 0x20)
                    TriangleStepCounter = 0;
            }
        }

        // DEBUG
        static int bitshift = 0;

        /// 
        /// ノイズチャネル 乱数生成器
        /// 
        public static void NoiseRandomNumberGenerator()
        {
            int bit0;
            int bit1;

            bit0 = 0;
            bit1 = 0;

            // 乱数生成は 2 回につき 1 回だけ実行される
            NoiseShiftFlag = !NoiseShiftFlag;

            if (NoiseShiftFlag == true)
                return;

            NoiseShiftRegister <<= 1;
            NoiseShiftRegister &= 0x7FFF;
            //NoiseShiftRegister |= bitshift;

            switch (NoiseRandomGeneratorMode)
            {
                case 0: // 32767
                    bit0 = (NoiseShiftRegister & 0x2000) > 0 ? 1 : 0;
                    bit1 = (NoiseShiftRegister & 0x4000) > 0 ? 1 : 0;
                    break;
                case 1: // 93
                    bit0 = (NoiseShiftRegister & 0x100) > 0 ? 1 : 0;
                    bit1 = (NoiseShiftRegister & 0x4000) > 0 ? 1 : 0;
                    break;
            }
            //bitshift = (bit0 ^ bit1);
            NoiseShiftRegister |= (bit0 ^ bit1);
        }

        /// 
        /// 
        /// 
        static byte VolumePrev = 0;

        /// 
        /// 現在処理中の(音声に関する)フレームの音量の値を返す
        /// 44.1 KHz の場合、1 秒間に 44,100 フレーム
        /// 
        /// 
        public static short GetCurrentVolume()
        {
            short result;
            short volume = 0;

            // 矩形波 1
            if (SquareChannel1Enable == true && Square1SilenceFlag == false)
            {
                if (Square1LengthCounter != 0)
                    volume += (short)((Square1Addition / AdditionCount) - 0);
            }

            // 矩形波 2
            if (SquareChannel2Enable == true && Square2SilenceFlag == false)
            {
                if (Square2LengthCounter != 0)
                    volume += (short)((Square2Addition / AdditionCount) - 0);
            }

            // 三角波
            if (TriangleChannelEnable == true)
            {
                if (TriangleLengthCounter != 0 && LinearCounter != 0)
                    volume += (short)((TriangleAddition / AdditionCount) - 0);
            }

            // ノイズチャネル
            if (NoiseChannelEnable == true)
            {
                if (NoiseLengthCounter != 0)
                    volume += (short)((NoiseAddition / AdditionCount) - 0);
            }

            // DEBUG
            //if (volume != 0)
            //    Console.WriteLine("{0}", volume);

            // 聞こえるくらいボリュームを上げる
            volume <<= 8;

            // 積算用の変数をクリア
            AdditionCount = 0;
            Square1Addition = 0;
            Square2Addition = 0;
            TriangleAddition = 0;
            NoiseAddition = 0;

            //VolumeChange += volume;
            //VolumeChange /= 3;

            /*
            if (VolumePrev == 128)
            {
                result = (byte)(128 + (volume / 2));
            }
            else
            {
                result = (byte)(128 + volume);
                if (result == 128)
                    result = (byte)(128 + (VolumePrev - 128));
            }
            VolumePrev = result;
             */
            //if (volume > 64)
            //    Console.WriteLine("V {0}", volume);

            //volume = (byte)(Math.Abs(prev_volume - volume) >> 1);
           // prev_volume = volume;


            return volume;
        }

        /// 
        /// 矩形波 1 のディケイの計算をする
        /// 
        public static void CalculateSquare1DecayedVolume()
        {
            if (Square1DecayedVolume > 0)
            {
                Square1DecayedVolume--;

                if (Square1DecayedVolume == 0)
                {
                    // ディケイリロード有効
                    if (Square1LengthCounterDisable == true)
                    {
                        Square1DecayedVolume = 0x0F;
                    }
                }
            }
        }

        /// 
        /// 矩形波 2 のディケイの計算をする
        /// 
        public static void CalculateSquare2DecayedVolume()
        {
            if (Square2DecayedVolume > 0)
            {
                Square2DecayedVolume--;

                if (Square2DecayedVolume == 0)
                {
                    // ディケイリロード有効
                    if (Square2LengthCounterDisable == true)
                    {
                        Square2DecayedVolume = 0x0F;
                    }
                }
            }
        }

        /// 
        /// ノイズチャネルのディケイの計算をする
        /// 
        public static void CalculateNoiseDecayedVolume()
        {
            if (NoiseDecayedVolume > 0)
            {
                NoiseDecayedVolume--;

                if (NoiseDecayedVolume == 0)
                {
                    // ディケイリロード有効
                    if (NoiseLengthCounterDisable == true)
                    {
                        NoiseDecayedVolume = 0x0F;
                    }
                }
            }
        }

        /// 
        /// 矩形波 1 の音量を積算する
        /// 
        /// ファミコンの波形は 1.79MHz で生成されるので、
        /// 44.1 KHz 等、PC の標準的なサンプリング周波数に
        /// ダウンサンプリングするために、いったん
        /// 1 フレーム内 (1 / 44,100 秒) の音量の和を出す。
        /// 後で平均値を求めて 1 フレームの音量を決定する
        /// 
        /// 
        public static void CalculateSquare1Addition()
        {
            int square_value;
            int positive_threshold;

            //if (SquareChannel1Enable == false)
            //    return;

            square_value = 0;
            positive_threshold = 0;

            switch (Square1DutyCycleType)
            {
                case 0: // 2/14
                    positive_threshold = 2;
                    break;
                case 1: // 4/12
                    positive_threshold = 4;
                    break;
                case 2: // 8/ 8
                    positive_threshold = 8;
                    break;
                case 3: // 12/ 4
                    positive_threshold = 12;
                    break;
            }

            // デューティサイクルカウンタが正の状態になっていたら
            if (Square1DutyCycleCounter < positive_threshold)
            {
                // ディケイが無効の時は音量そのまま
                if (Square1DecayDisable == true)
                {
                    square_value = Square1VolumeAndDecayRate;
                }
                // ディケイが有効の時はディケイがかかった音量
                else
                {
                    square_value = Square1DecayedVolume;
                }
            }

            Square1Addition += square_value;
        }

        /// 
        /// 矩形波 2 の音量を積算する
        /// 
        /// ファミコンの波形は 1.79MHz で生成されるので、
        /// 44.1 KHz 等、PC の標準的なサンプリング周波数に
        /// ダウンサンプリングするために、いったん
        /// 1 フレーム内 (1 / 44,100 秒) の音量の和を出す。
        /// 後で平均値を求めて 1 フレームの音量を決定する
        /// 
        /// 
        public static void CalculateSquare2Addition()
        {
            int square_value;
            int positive_threshold;

            //if (SquareChannel2Enable == false)
            //    return;

            square_value = 0;
            positive_threshold = 0;

            switch (Square2DutyCycleType)
            {
                case 0: // 2/14
                    positive_threshold = 2;
                    break;
                case 1: // 4/12
                    positive_threshold = 4;
                    break;
                case 2: // 8/ 8
                    positive_threshold = 8;
                    break;
                case 3: // 12/ 4
                    positive_threshold = 12;
                    break;
            }

            // デューティサイクルカウンタが正の状態になっていたら
            if (Square2DutyCycleCounter < positive_threshold)
            {
                // ディケイが無効の時は音量そのまま
                if (Square2DecayDisable == true)
                {
                    square_value = Square2VolumeAndDecayRate;
                }
                // ディケイが有効の時はディケイがかかった音量
                else
                {
                    square_value = Square2DecayedVolume;
                }
            }

            Square2Addition += square_value;
        }

        /// 
        /// 三角波の音量を積算する
        /// 
        /// ファミコンの波形は 1.79MHz で生成されるので、
        /// 44.1 KHz 等、PC の標準的なサンプリング周波数に
        /// ダウンサンプリングするために、いったん
        /// 1 フレーム内 (1 / 44,100 秒) の音量の和を出す。
        /// 後で平均値を求めて 1 フレームの音量を決定する
        /// 
        /// 
        public static void CalculateTriangleAddition()
        {
            int triangle_value;

            //if (TriangleChannelEnable == false)
            //    return;

            // 5 ビット目が立っていなかったら
            // 逆数にする
            if ((TriangleStepCounter & 0x10) == 0)
                triangle_value = 0x0F - (TriangleStepCounter & 0x0F);
            else
                triangle_value = (TriangleStepCounter & 0x0F);

            TriangleAddition += triangle_value;
        }

        /// 
        /// ノイズチャネルの音量を積算する
        /// 
        /// ファミコンの波形は 1.79MHz で生成されるので、
        /// 44.1 KHz 等、PC の標準的なサンプリング周波数に
        /// ダウンサンプリングするために、いったん
        /// 1 フレーム内 (1 / 44,100 秒) の音量の和を出す。
        /// 後で平均値を求めて 1 フレームの音量を決定する
        /// 
        /// 
        public static void CalculateNoiseAddition()
        {
            int noise_value;

            noise_value = 0;

            if ((NoiseShiftRegister & 0x4000) == 0)
            {
                //Console.WriteLine("NOISE : {0}", NoiseShiftRegister);
                // ディケイが無効の時は音量そのまま
                if (NoiseDecayDisable == true)
                {
                    noise_value = NoiseVolumeAndDecayRate;
                }
                // ディケイが有効の時はディケイがかかった音量
                else
                {
                    noise_value = NoiseDecayedVolume;
                }
            }

            NoiseAddition += noise_value;
        }


        // TODO APU の中から呼び出すように変更するか検討する
        // 今のところこれは、CPUの 1 フレーム経過後の
        // 処理から呼び出されるようになっているが、
        // APU内のクロック毎の処理から呼び出した方が
        // 読みやすいかもしれない。
        /// 
        /// 長さカウンタを 1 ステップ分だけ進める
        /// 
        ///
        public static void StepLengthCounter()
        {
            // 矩形波 1 の長さカウンタ
            if (Square1LengthCounterDisable == false)
            {
                if (Square1LengthCounter != 0)
                    Square1LengthCounter--;
            }

            // 矩形波 2 の長さカウンタ
            if (Square2LengthCounterDisable == false)
            {
                if (Square2LengthCounter != 0)
                    Square2LengthCounter--;
            }

            // 三角波 の長さカウンタ
            if (TriangleLengthCounterDisable == false)
            {
                if (TriangleLengthCounter != 0)
                    TriangleLengthCounter--;
            }

            // ノイズチャネル の長さカウンタ
            if (NoiseLengthCounterDisable == false)
            {
                if (NoiseLengthCounter != 0)
                    NoiseLengthCounter--;
            }
        }

        
        /// 
        /// 三角波の線形カウンタを 1 ステップ分だけ進める
        /// 
        public static void StepLinearCounter()
        {
            if (TriangleLoadModeFlag == true)
            {
                LinearCounter = (NesStorage.IO2[0x08] & 0x7F);
            }
            else if (LinearCounter > 0)
            {
                LinearCounter--;
            }

            if ((byte)(NesStorage.IO2[0x08] & 0x80) == 0)
            {
                TriangleLoadModeFlag = false;
            }
        }

        /// 
        /// 矩形波 1 のスウィープ処理を実行
        /// 
        public static void Square1Sweep()
        {
            int new_wavelength;
            int wavelength;

            // 処理しない条件
            if (SquareChannel1Enable == false)
                return;

            if (Square1SweepShiftAmount == 0)
                return;

            if (Square1LengthCounter == 0)
                return;

            // 初期化
            new_wavelength = 0;

            wavelength = NesStorage.IO2[0x02];
            wavelength |= ((NesStorage.IO2[0x03] & 0x07) << 8);

            // 処理しない条件
            if (wavelength <= 0x008)
                return;


            // 周波数レジスタの更新処理
            switch (Square1SweepDirection)
            {
                case 0: // 増加
                    new_wavelength = wavelength + (wavelength >> Square1SweepShiftAmount);

                    // 下から数えて 12 ビット目が立っていたら
                    // (計算結果からキャリーが発生したら)、
                    // 動作を停止する
                    if ((new_wavelength & 0x800) > 0)
                    {
                        Square1SilenceFlag = true;
                        return;
                    }

                    break;
                case 1: // 減少
                    new_wavelength = wavelength - (wavelength >> Square1SweepShiftAmount) - 1;
                    break;
            }

            Square1SilenceFlag = false;
            NesStorage.IO2[0x02] = (byte)(new_wavelength & 0xFF);
            NesStorage.IO2[0x03] &= 0xF8;
            NesStorage.IO2[0x03] = (byte)((new_wavelength >> 8) & 0x07);
        }

        /// 
        /// 矩形波 2 のスウィープ処理を実行
        /// 
        public static void Square2Sweep()
        {
            int new_wavelength;
            int wavelength;

            // 処理しない条件
            if (SquareChannel2Enable == false)
                return;

            if (Square2SweepShiftAmount == 0)
                return;

            if (Square2LengthCounter == 0)
                return;

            // 初期化
            new_wavelength = 0;

            wavelength = NesStorage.IO2[0x06];
            wavelength |= ((NesStorage.IO2[0x07] & 0x07) << 8);

            // 処理しない条件
            if (wavelength <= 0x008)
                return;


            // 周波数レジスタの更新処理
            switch (Square2SweepDirection)
            {
                case 0: // 増加
                    new_wavelength = wavelength + (wavelength >> Square2SweepShiftAmount);

                    // 下から数えて 12 ビット目が立っていたら
                    // (計算結果からキャリーが発生したら)、
                    // 動作を停止する
                    if ((new_wavelength & 0x800) > 0)
                    {
                        Square2SilenceFlag = true;
                        return;
                    }

                    break;
                case 1: // 減少
                    new_wavelength = wavelength - (wavelength >> Square2SweepShiftAmount) - 1;
                    break;
            }

            Square2SilenceFlag = false;
            NesStorage.IO2[0x06] = (byte)(new_wavelength & 0xFF);
            NesStorage.IO2[0x07] &= 0xF8;
            NesStorage.IO2[0x07] = (byte)((new_wavelength >> 8) & 0x07);
        }


        static int RingBufferFilled = 0;

        /// 
        /// プログラマブルタイマをクロック分だけ進める
        /// 
        ///
        public static void StepProgrammableTimer(int clock)
        {
            // システムリセットから最初の 2048 クロックは
            // 処理を停止する
            if (SoundFirstInitFlag == false)
            {
                SoundFirstInitCounter += clock;

                if (SoundFirstInitCounter > 2048)
                    SoundFirstInitFlag = true;
                else
                    return;

                clock = SoundFirstInitCounter - 2048;
            }

            // 矩形波 1 ---------------------------------------------
            if (SquareChannel1Enable == true)
            {
                Square1ProgrammableTimer -= clock;

                // 終わりまで行ったらリロードする
                while (Square1ProgrammableTimer < 0)
                {
                    int timer;
                    timer = NesStorage.IO2[0x02];
                    timer |= ((NesStorage.IO2[0x03] & 0x07) << 8);
                    timer += (Square1ProgrammableTimer + 1);

                    Square1ProgrammableTimer = timer;

                    // デューティサイクルジェネレータで波形を作る
                    IncrementSquare1DutyCycleCounter();
                }
            }
            // 矩形波 2 ---------------------------------------------
            if (SquareChannel2Enable == true)
            {
                Square2ProgrammableTimer -= clock;

                // 終わりまで行ったらリロードする
                while (Square2ProgrammableTimer < 0)
                {
                    int timer;
                    timer = NesStorage.IO2[0x06];
                    timer |= ((NesStorage.IO2[0x07] & 0x07) << 8);
                    timer += (Square2ProgrammableTimer + 1);

                    Square2ProgrammableTimer = timer;

                    // デューティサイクルジェネレータで波形を作る
                    IncrementSquare2DutyCycleCounter();
                }
            }
            // 三角波 -----------------------------------------------
            if (TriangleChannelEnable == true)
            {
                TriangleProgrammableTimer -= clock;

                // 終わりまで行ったらリロードする
                while (TriangleProgrammableTimer < 0)
                {
                    int timer;
                    timer = NesStorage.IO2[0x0A];
                    timer |= ((NesStorage.IO2[0x0B] & 0x07) << 8);
                    timer += (TriangleProgrammableTimer + 1);

                    TriangleProgrammableTimer = timer;

                    // 三角波生成器で波形を作る
                    IncrementTriangleStepCounter();
                }
            }

            // ノイズ -----------------------------------------------
            if (NoiseChannelEnable == true)
            {
                NoiseProgrammableTimer -= clock;

                // 終わりまで行ったらリロードする
                while (NoiseProgrammableTimer < 0)
                {
                    int rate;
                    int timer;

                    rate = NesStorage.IO2[0x0E] & 0x0F;
                    timer = NoiseWavelengthTable[rate];
                    timer += (NoiseProgrammableTimer + 1);

                    NoiseProgrammableTimer = timer;

                    // 乱数生成器で波形を作る
                    NoiseRandomNumberGenerator();
                }
            }

            // 矩形波三角波の音量を積算する -----------------------
            for (int i = 0; i < clock; i++)
            {
                AdditionCount++;

                //if (SquareChannel1Enable == true)
                    CalculateSquare1Addition();

                //if (SquareChannel2Enable == true)
                    CalculateSquare2Addition();

                //if (TriangleChannelEnable == true)
                    CalculateTriangleAddition();
                
                //if (NoiseChannelEnable == true)
                    CalculateNoiseAddition();
            }

            // 1 / 4 フレームの計算 ---------------------------------
            ClockQuarterFrame += clock;
            if (ClockQuarterFrame > AdditionQuarterFrame)
            {
                // 三角波の線形カウンタ計算
                if (TriangleChannelEnable == true)
                {
                    ClockQuarterFrame -= AdditionQuarterFrame;
                    StepLinearCounter();
                }

                // 矩形波 1 のディケイの計算
                if (SquareChannel1Enable == true)
                {
                    Square1DecayCounter++;
                    if (Square1DecayCounter > Square1VolumeAndDecayRate)
                    {
                        Square1DecayCounter = 0;
                        CalculateSquare1DecayedVolume();
                    }
                }

                // 矩形波 2 のディケイの計算
                if (SquareChannel2Enable == true)
                {
                    Square2DecayCounter++;
                    if (Square2DecayCounter > Square2VolumeAndDecayRate)
                    {
                        Square2DecayCounter = 0;
                        CalculateSquare2DecayedVolume();
                    }
                }

                if (NoiseChannelEnable == true)
                {
                    // ノイズチャネルのディケイの計算
                    NoiseDecayCounter++;
                    if (NoiseDecayCounter > NoiseVolumeAndDecayRate)
                    {
                        NoiseDecayCounter = 0;
                        CalculateNoiseDecayedVolume();
                    }
                }

                // 1 / 2 フレームの計算
                // スウィープユニット用
                HalfFrameFlag = !HalfFrameFlag;

                if (HalfFrameFlag == false)
                {
                    // 矩形波 1 のスウィープ処理
                    if (SquareChannel1Enable == true && Square1SweepEnable == true)
                    {
                        Square1SweepCounter++;

                        if (Square1SweepCounter >= Square1SweepUpdateRate + 1)
                        {
                            Square1SweepCounter = 0;
                            Square1Sweep();
                        }
                    }

                    // 矩形波 2 のスウィープ処理
                    if (SquareChannel2Enable == true && Square2SweepEnable == true)
                    {
                        Square2SweepCounter++;

                        if (Square2SweepCounter >= Square2SweepUpdateRate + 1)
                        {
                            Square2SweepCounter = 0;
                            Square2Sweep();
                        }
                    }
                }
            }

            // クロック積算 (44.1 KHz 用) ---------------------------
            ClockAddition += clock;

            if (ClockAddition > AdditionLimit44)
            {
                ClockAddition -= AdditionLimit44;

                //semaphore.WaitOne();
                RingBuffer[RingBufferPointer] = GetCurrentVolume();
                RingBufferPointer++;

                if ((RingBufferPointer % (44100 / 20)) == 0)
                {
                    RingBufferFilled = RingBufferPointer;
                    //RingBufferFilled *= (44100 / 60);
                    //Console.WriteLine("FIll {0} {1}", RingBufferFilled, RingBufferPointer);
                }

                if (RingBufferPointer >= 44100)
                {
                    RingBufferPointer = 0;

                    /*try
                    {
                        secondaryBuffer.Write(0, RingBuffer, LockFlag.None);
                        secondaryBuffer.Play(0, BufferPlayFlags.Default);
                    }
                    catch (Exception)
                    {

                    }*/
                }

                //semaphore.Release();

                //Console.WriteLine("Volume : {0}", GetCurrentVolume());
            }

        }
    }
}

Windows RTでADAMem SDL

はじめにVisual Studio 2012(VS Express for Desktop)をインストールします。
Visual Studio 2012 Express Editionのダウンロードとインストール

つぎにARM用SDLをダウンロードします。
Desktop apps ported to Windows RT

includeフォルダはSDLにリネームしてC:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\SDLに配置します。
SDL.lib、SDLmain.libはC:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\libに配置します。

ADAMem SDLをまずはwin32でビルドしてみました。
ADAMem DOS and ADAMem SDL v1.81 - Page 2 - ColecoVision / Adam - AtariAge Forums

AdamemSDL.c

//	if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0 )
	if ( SDL_Init(SDL_INIT_AUDIO) < 0 )
	{
		if (Verbose) printf("FAILED: %s\n", SDL_GetError());
		return 0;
	}

Z80IO.h

;
//#if (__GNUC__ <= 3 && __GNUC__MINOR__ <= 4) \
//	|| (__GNUC__ >= 2 && __GNUC__MINOR__ >= 7)
//#define FASTCALL        __attribute__ ((regparm(3)))
//#ifdef INLINE_MEM
//#define INLINE_MEM_GNU
//#endif
//#else
#define FASTCALL
//#endif

そしてVisual Studio 2012でARMをビルドできるようにします。ARM用のSDL.lib、SDLmain.libはプロジェクトに追加が必要でした。
[how to] compile and port win32 apps to Windows RT ARM