using System;
using System.IO;
using System.Linq;
using System.Media;
using System.Windows.Forms;
namespace playwav2
{
struct Note
{
public int num;
public int tick;
public Note(int num, int tick)
{
this.num = num;
this.tick = tick;
}
}
public partial class Form1 : Form
{
private const int sampleRate = 48000;
private const int timebase = 24;
private int tempo = 120;
private SoundPlayer player = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var stream = CreateSound();
PlaySound(stream);
}
private void button2_Click(object sender, EventArgs e)
{
StopSound();
}
private void PlaySound(Stream stream)
{
StopSound();
player = new SoundPlayer(stream);
player.Play();
}
private void StopSound()
{
if (player != null)
{
player.Stop();
player = null;
}
}
private MemoryStream CreateSound()
{
var nChannels = 1;
var wBitsPerSample = 8;
var nBlockAlign = nChannels * (wBitsPerSample / 8);
var nAvgBytesPerSec = sampleRate * nBlockAlign;
var data = CreateData();
//
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
// RIFF
bw.Write("RIFF".ToCharArray());
bw.Write((uint)(36 + data.Length)); // cksize
bw.Write("WAVE".ToCharArray());
// fmt
bw.Write("fmt ".ToCharArray());
bw.Write((uint)16); // cksize
// WAVEFORMATEX
bw.Write((ushort)1); // wFormatTag 1:WAVE_FORMAT_PCM
bw.Write((ushort)nChannels);
bw.Write((uint)sampleRate); // nSamplesPerSec
bw.Write((uint)nAvgBytesPerSec);
bw.Write((ushort)nBlockAlign);
bw.Write((ushort)wBitsPerSample);
// data
bw.Write("data".ToCharArray());
bw.Write((uint)data.Length); // cksize
bw.Write(data);
//using (var fs = new FileStream(@"c:\tmp\sample.wav", FileMode.Create, FileAccess.Write))
//{
// ms.Position = 0;
// ms.CopyTo(fs);
//}
ms.Position = 0;
return ms;
}
private byte[] CreateData()
{
tempo = 150;
int dataLen = (int)(TickToSample(timebase * 8));
//var data = new byte[dataLen];
var data = Enumerable.Repeat<byte>(0x80, dataLen).ToArray();
// note number, tick
byte[,] ch1 = {
{ 60, 24 },
{ 62, 24 },
{ 64, 24 },
{ 65, 24 },
{ 64, 24 },
{ 62, 24 },
{ 60, 24 },
{ 0, 24 },
};
byte[,] ch2 = {
{ 48, 24 },
{ 0, 24 },
{ 48, 24 },
{ 0, 24 },
{ 48, 24 },
{ 0, 24 },
{ 48, 24 },
{ 0, 24 },
};
if (checkBox1.Checked) MakeWaveform(ref data, ch1, 10);
if (checkBox2.Checked) MakeWaveform(ref data, ch2, 8);
return data;
}
private void MakeWaveform(ref byte[] data, byte[,] notes, int gain)
{
double pos = 0;
for (var i = 0; i < notes.GetLength(0); i++)
{
double sample = TickToSample(notes[i, 1]);
if (notes[i, 0] > 0)
{
double freq = 440 * Math.Pow(2, (notes[i, 0] - 69) / 12.0);
double f = 0;
var epos = (int)(pos + sample);
for (var j = (int)pos; j < epos; j++)
{
f += freq;
if (sampleRate <= f) f -= sampleRate;
double t = f / sampleRate;
data[j] += (byte)((t < 0.5 ? 1 : -1) * gain);
}
}
pos += sample;
}
}
double TickToSample(int tick)
{
return (tick / (double)timebase) * (60.0 / tempo) * sampleRate;
}
}
}