「VCS/WaveLoop」の編集履歴(バックアップ)一覧はこちら

VCS/WaveLoop - (2018/05/23 (水) 08:33:00) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual Studio Community 2017| |実行環境|Microsoft Windows 10 Home (64-bit)| |プロジェクトの種類|Visual C# / Windows フォーム アプリケーション (.NET Framework)| |プロジェクト名|WaveLoop| -参考 [[マーシャリングに関する話題>http://www.cactussoft.co.jp/Sarbo/divManageUse1.html]] Form1.cs #highlight(c#){{ using System; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Windows.Forms; using static WaveLoop.WinApi; namespace WaveLoop { public partial class Form1 : Form { public struct Buffers { public WAVEHDR wh; public IntPtr waveform; } private const int SAMPLE_RATE = 44100; private const int BUFFERS = 2; private const int BUF_LEN = 22050; private IntPtr hwo = IntPtr.Zero; private Buffers[] buffers = new Buffers[BUFFERS]; private int wavefreq; private int phase; private bool playing = false; public Form1() { InitializeComponent(); } protected override void WndProc(ref Message m) { base.WndProc(ref m); switch (m.Msg) { case MM_WOM_DONE: if (playing) { GenerateWave((WAVEHDR)m.GetLParam(typeof(WAVEHDR))); } break; } } private void button1_Click(object sender, EventArgs e) { Play(); } private void button2_Click(object sender, EventArgs e) { Stop(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { Stop(); } private void GenerateWave(WAVEHDR wh) { byte[] data = Enumerable.Repeat((byte)128, BUF_LEN).ToArray(); for (var i = 0; i < BUF_LEN; i++) { phase += wavefreq; if (SAMPLE_RATE <= phase) phase -= SAMPLE_RATE; double t = phase / (double)SAMPLE_RATE; data[i] += (byte)((t < 0.5 ? 1 : -1) * 10); } Marshal.Copy(data, 0, wh.lpData, data.Length); waveOutWrite(hwo, wh, (uint)Marshal.SizeOf<WAVEHDR>()); } //// // 再生 private void Play() { Trace.WriteLine("Play()"); button1.Enabled = false; playing = true; SetFreq(440); uint mmr; WAVEFORMATEX wfx = new WAVEFORMATEX(); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 1; wfx.nSamplesPerSec = SAMPLE_RATE; wfx.nAvgBytesPerSec = SAMPLE_RATE; wfx.nBlockAlign = 1; wfx.wBitsPerSample = 8; wfx.cbSize = 0; mmr = waveOutOpen(ref hwo, WAVE_MAPPER, ref wfx, Handle, 0, CALLBACK_WINDOW); Trace.WriteLine("waveOutOpen:" + mmr); for (var i = 0; i < BUFFERS; i++) { IntPtr waveform = Marshal.AllocHGlobal(BUF_LEN); WAVEHDR wh = new WAVEHDR(); wh.lpData = waveform; wh.dwBufferLength = BUF_LEN; wh.dwFlags = 0; mmr = waveOutPrepareHeader(hwo, wh, (uint)Marshal.SizeOf<WAVEHDR>()); Trace.WriteLine("waveOutPrepareHeader:" + mmr); GenerateWave(wh); buffers[i].wh = wh; buffers[i].waveform = waveform; } } // 停止 private void Stop() { Trace.WriteLine("Stop()"); button1.Enabled = true; playing = false; if (hwo != IntPtr.Zero) { uint mmr; mmr = waveOutReset(hwo); Trace.WriteLine("waveOutReset:" + mmr); for (var i = 0; i < BUFFERS; i++) { mmr = waveOutUnprepareHeader(hwo, buffers[i].wh, (uint)Marshal.SizeOf<WAVEHDR>()); Trace.WriteLine("waveOutUnprepareHeader:" + mmr); Marshal.FreeHGlobal(buffers[i].waveform); } mmr = waveOutClose(hwo); Trace.WriteLine("waveOutClose:" + mmr); hwo = IntPtr.Zero; } } private void SetFreq(int freq) { wavefreq = freq; phase = 0; } } public class WinApi { [StructLayout(LayoutKind.Sequential)] public struct WAVEFORMATEX { public ushort wFormatTag; public ushort nChannels; public uint nSamplesPerSec; public uint nAvgBytesPerSec; public ushort nBlockAlign; public ushort wBitsPerSample; public ushort cbSize; } [StructLayout(LayoutKind.Sequential)] public class WAVEHDR { public IntPtr lpData; public uint dwBufferLength; public uint dwBytesRecorded; public uint dwUser; public uint dwFlags; public uint dwLoops; public IntPtr lpNext; public uint reserved; } [DllImport("winmm.dll")] public static extern uint waveOutOpen(ref IntPtr phwo, uint uDeviceID, ref WAVEFORMATEX pwfx, IntPtr dwCallback, uint dwCallbackInstance, uint fdwOpen); [DllImport("winmm.dll")] public static extern uint waveOutClose(IntPtr hwo); [DllImport("winmm.dll")] public static extern uint waveOutPrepareHeader(IntPtr hwo, WAVEHDR pwh, uint cbwh); [DllImport("winmm.dll")] public static extern uint waveOutUnprepareHeader(IntPtr hwo, WAVEHDR pwh, uint cbwh); [DllImport("winmm.dll")] public static extern uint waveOutWrite(IntPtr hwo, WAVEHDR pwh, uint cbwh); [DllImport("winmm.dll")] public static extern uint waveOutReset(IntPtr hwo); public const ushort WAVE_FORMAT_PCM = 1; public const uint WAVE_MAPPER = unchecked((uint)-1); public const uint CALLBACK_WINDOW = 0x00010000; public const int MM_WOM_OPEN = 0x3BB; public const int MM_WOM_CLOSE = 0x3BC; public const int MM_WOM_DONE = 0x3BD; public const uint WAVERR_STILLPLAYING = 33; } } }}
|開発環境|Microsoft Visual Studio Community 2017| |実行環境|Microsoft Windows 10 Home (64-bit)| |プロジェクトの種類|Visual C# / Windows フォーム アプリケーション (.NET Framework)| |プロジェクト名|WaveLoop| -参考 [[マーシャリングに関する話題>http://www.cactussoft.co.jp/Sarbo/divManageUse1.html]] Form1.cs #highlight(c#){{ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Windows.Forms; using static WaveLoop.WinApi; namespace WaveLoop { public partial class Form1 : Form { private struct Buffers { public WAVEHDR wh; public IntPtr waveform; } private struct Sequence { public int msec; public int freq; } private const int SAMPLE_RATE = 44100; private const int BUFFERS = 2; private const int BUF_LEN = 22050; private const int TIMEBASE = 24; private IntPtr hwo = IntPtr.Zero; private Buffers[] buffers = new Buffers[BUFFERS]; private bool playing = false; private int wavefreq; private int phase; private List<Sequence> seq = new List<Sequence>(); private int nseq; private DateTime start; public Form1() { InitializeComponent(); Init(); } protected override void WndProc(ref Message m) { base.WndProc(ref m); switch (m.Msg) { case MM_WOM_DONE: if (playing) { TimerProc(); GenerateWave((WAVEHDR)m.GetLParam(typeof(WAVEHDR))); } break; } } private void button1_Click(object sender, EventArgs e) { Play(); } private void button2_Click(object sender, EventArgs e) { Stop(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { Stop(); } //-- private void Init() { int tempo = 120; int[] notes = { 60, 24, 62, 24, 64, 24, 65, 24, 64, 24, 62, 24, 60, 24, 0, 24, }; Sequence s; int elapse = 100; // wait for (var i = 0; i < notes.Length; i += 2) { int gate = (int)((notes[i + 1] / (double)TIMEBASE) * (60.0 / tempo) * 1000); s.msec = elapse; s.freq = (notes[i] <= 0) ? 0 : (int)(440 * Math.Pow(2, (notes[i] - 69) / 12.0)); seq.Add(s); elapse += gate; } s.msec = elapse; s.freq = 0; seq.Add(s); } private void TimerProc() { int dur = (int)((DateTime.Now - start).TotalMilliseconds); if (seq[nseq].msec <= dur) { SetFreq(seq[nseq].freq); nseq++; if (seq.Count <= nseq) { //Stop(); playing = false; } } } private void GenerateWave(WAVEHDR wh) { byte[] data = Enumerable.Repeat((byte)128, BUF_LEN).ToArray(); for (var i = 0; i < BUF_LEN; i++) { phase += wavefreq; if (SAMPLE_RATE <= phase) phase -= SAMPLE_RATE; double t = phase / (double)SAMPLE_RATE; data[i] += (byte)((t < 0.5 ? 1 : -1) * 10); } Marshal.Copy(data, 0, wh.lpData, data.Length); waveOutWrite(hwo, wh, (uint)Marshal.SizeOf<WAVEHDR>()); } //-- // 再生 private void Play() { Trace.WriteLine("Play()"); if (playing) return; playing = true; SetFreq(0); nseq = 0; start = DateTime.Now; uint mmr; WAVEFORMATEX wfx = new WAVEFORMATEX(); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 1; wfx.nSamplesPerSec = SAMPLE_RATE; wfx.nAvgBytesPerSec = SAMPLE_RATE; wfx.nBlockAlign = 1; wfx.wBitsPerSample = 8; wfx.cbSize = 0; mmr = waveOutOpen(ref hwo, WAVE_MAPPER, ref wfx, Handle, 0, CALLBACK_WINDOW); Trace.WriteLine("waveOutOpen:" + mmr); for (var i = 0; i < BUFFERS; i++) { IntPtr waveform = Marshal.AllocHGlobal(BUF_LEN); WAVEHDR wh = new WAVEHDR(); wh.lpData = waveform; wh.dwBufferLength = BUF_LEN; wh.dwFlags = 0; mmr = waveOutPrepareHeader(hwo, wh, (uint)Marshal.SizeOf<WAVEHDR>()); Trace.WriteLine("waveOutPrepareHeader:" + mmr); GenerateWave(wh); buffers[i].wh = wh; buffers[i].waveform = waveform; } } // 停止 private void Stop() { Trace.WriteLine("Stop()"); playing = false; if (hwo != IntPtr.Zero) { uint mmr; mmr = waveOutReset(hwo); Trace.WriteLine("waveOutReset:" + mmr); for (var i = 0; i < BUFFERS; i++) { mmr = waveOutUnprepareHeader(hwo, buffers[i].wh, (uint)Marshal.SizeOf<WAVEHDR>()); Trace.WriteLine("waveOutUnprepareHeader:" + mmr); Marshal.FreeHGlobal(buffers[i].waveform); } mmr = waveOutClose(hwo); Trace.WriteLine("waveOutClose:" + mmr); hwo = IntPtr.Zero; } } // 周波数セット private void SetFreq(int freq) { wavefreq = freq; phase = 0; } } public class WinApi { [StructLayout(LayoutKind.Sequential)] public struct WAVEFORMATEX { public ushort wFormatTag; public ushort nChannels; public uint nSamplesPerSec; public uint nAvgBytesPerSec; public ushort nBlockAlign; public ushort wBitsPerSample; public ushort cbSize; } [StructLayout(LayoutKind.Sequential)] public class WAVEHDR // マーシャリングのためstructからclassに { public IntPtr lpData; public uint dwBufferLength; public uint dwBytesRecorded; public uint dwUser; public uint dwFlags; public uint dwLoops; public IntPtr lpNext; public uint reserved; } [DllImport("winmm.dll")] public static extern uint waveOutOpen(ref IntPtr phwo, uint uDeviceID, ref WAVEFORMATEX pwfx, IntPtr dwCallback, uint dwCallbackInstance, uint fdwOpen); [DllImport("winmm.dll")] public static extern uint waveOutClose(IntPtr hwo); [DllImport("winmm.dll")] public static extern uint waveOutPrepareHeader(IntPtr hwo, WAVEHDR pwh, uint cbwh); [DllImport("winmm.dll")] public static extern uint waveOutUnprepareHeader(IntPtr hwo, WAVEHDR pwh, uint cbwh); [DllImport("winmm.dll")] public static extern uint waveOutWrite(IntPtr hwo, WAVEHDR pwh, uint cbwh); [DllImport("winmm.dll")] public static extern uint waveOutReset(IntPtr hwo); public const ushort WAVE_FORMAT_PCM = 1; public const uint WAVE_MAPPER = unchecked((uint)-1); public const uint CALLBACK_WINDOW = 0x00010000; public const int MM_WOM_OPEN = 0x3BB; public const int MM_WOM_CLOSE = 0x3BC; public const int MM_WOM_DONE = 0x3BD; public const uint WAVERR_STILLPLAYING = 33; } } }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: