You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
6.9 KiB
C#

using IntelOrca.Launchpad;
using Midi;
using System;
using System.Threading;
namespace IntelOrca.LaunchpadTests
{
class RainSequencer
{
const int NumCols = 16;
const int NumRows = 8;
private LaunchpadDevice mLaunchpadDevice;
private bool[,] mSequence = new bool[NumCols, NumRows];
private bool[] mRemove = new bool[NumCols];
private int mSequenceOffset;
private int mColumnOffset;
private int mMode, mSoundType;
private int mConfirmTime;
private bool mForceDraw;
private int mTempo = 8 * 60;
OutputDevice mOutputDevice;
private int mInstrument = 0;
private int mPercussion = 0;
public RainSequencer(LaunchpadDevice device)
{
mLaunchpadDevice = device;
mOutputDevice = OutputDevice.InstalledDevices[0];
mOutputDevice.Open();
mLaunchpadDevice.ButtonPressed += mLaunchpadDevice_ButtonPressed;
/*
Random rand = new Random();
for (int y = 0; y < NumRows; y++)
for (int x = 0; x < NumRows; x++)
if (rand.Next(0, 12) == 0)
mSequence[x, y] = true;
* */
}
private int SeqYtoButtonY(int y)
{
return 0;
}
private int ButtonYtoSeqY(int y)
{
return (y + NumRows - mSequenceOffset) % NumRows;
}
private int ButtonXtoColX(int x)
{
return (x + NumCols - mColumnOffset) % NumCols;
}
private void mLaunchpadDevice_ButtonPressed(object sender, ButtonPressEventArgs e)
{
if (e.Type == ButtonType.Grid) {
if (e.Y == 7) {
mRemove[ButtonXtoColX(e.X)] = !mRemove[ButtonXtoColX(e.X)];
if (mMode == 1)
PlayNoise(e.X);
} else {
mSequence[ButtonXtoColX(e.X), ButtonYtoSeqY(e.Y)] = !mSequence[ButtonXtoColX(e.X), ButtonYtoSeqY(e.Y)];
}
mForceDraw = true;
} else if (e.Type == ButtonType.Toolbar) {
switch (e.ToolbarButton) {
case ToolbarButton.Up:
mSequenceOffset = (mSequenceOffset + NumRows - 1) % NumRows;
break;
case ToolbarButton.Down:
mSequenceOffset = (mSequenceOffset + 1) % NumRows;
break;
case ToolbarButton.Left:
mColumnOffset = (mColumnOffset + NumCols - 1) % NumCols;
break;
case ToolbarButton.Right:
mColumnOffset = (mColumnOffset + 1) % NumCols;
break;
case ToolbarButton.Mixer:
mMode = (mMode == 0 ? 1 : 0);
break;
case ToolbarButton.Session:
if (mConfirmTime > 0) {
for (int y = 0; y < NumRows; y++)
for (int x = 0; x < NumCols; x++)
mSequence[x, y] = false;
mConfirmTime = 0;
} else {
mConfirmTime = 1000;
}
break;
}
mForceDraw = true;
} else if (e.Type == ButtonType.Side) {
switch (e.SidebarButton) {
case SideButton.Volume:
if (mTempo < 1980)
mTempo += 20;
break;
case SideButton.Pan:
if (mTempo > 20)
mTempo -= 20;
break;
case SideButton.SoundA:
if (mSoundType == 0) {
mPercussion = (mPercussion + 1) % (Percussion.OpenTriangle - Percussion.BassDrum2 + 1);
mOutputDevice.SendProgramChange(Channel.Channel1, (Instrument)mInstrument);
} else {
mSoundType = 0;
}
break;
case SideButton.SoundB:
if (mSoundType == 1) {
mInstrument = (mInstrument + 1) % 127;
mOutputDevice.SendProgramChange(Channel.Channel1, (Instrument)mInstrument);
} else {
mSoundType = 1;
}
break;
case SideButton.Arm:
mSequenceOffset = 0;
mColumnOffset = 0;
break;
}
}
}
public void Run()
{
long last_tick = Environment.TickCount;
long delay = 1;
long duration = 0;
while (true) {
delay = (int)(1000.0 / (mTempo / 60.0));
duration = Environment.TickCount - last_tick;
if (duration < delay) {
if (mForceDraw) {
Draw();
mForceDraw = false;
}
continue;
}
last_tick = Environment.TickCount;
mConfirmTime = Math.Max(0, mConfirmTime - (int)duration);
Update();
Draw();
}
}
private void PlayNoise(int tone)
{
new Thread(new ThreadStart(() => {
if (mSoundType == 0) {
mOutputDevice.SendPercussion(Percussion.BassDrum2 + mPercussion + tone, 127);
} else {
mOutputDevice.SendNoteOn(Channel.Channel1, Pitch.A4 + tone, 127);
Thread.Sleep((int)(1000.0 / (mTempo / 60.0)));
mOutputDevice.SendNoteOff(Channel.Channel1, Pitch.A4 + tone, 127);
}
// Console.Beep(100 * (tone + 3), 100);
})).Start();
}
private void DiscardRedBeats()
{
int y = ButtonYtoSeqY(7);
for (int x = 0; x < NumCols; x++)
if (mSequence[x, y] && mRemove[x])
mSequence[x, y] = false;
}
private void PlayBeats()
{
int y = ButtonYtoSeqY(7);
for (int x = 0; x < NumCols; x++)
if (mSequence[x, y])
PlayNoise(x);
}
private void Update()
{
if (mMode == 1)
return;
DiscardRedBeats();
mSequenceOffset = (mSequenceOffset + 1) % NumRows;
PlayBeats();
}
private void Draw()
{
ButtonBrightness[,] redgrid = new ButtonBrightness[8, 8];
ButtonBrightness[,] greengrid = new ButtonBrightness[8, 8];
for (int y = 0; y < 7; y++)
for (int x = 0; x < 8; x++)
if (mSequence[ButtonXtoColX(x), ButtonYtoSeqY(y)])
redgrid[x, y] = greengrid[x, y] = ButtonBrightness.Full;
for (int x = 0; x < 8; x++) {
ButtonBrightness brightness = (mSequence[ButtonXtoColX(x), ButtonYtoSeqY(7)] ? ButtonBrightness.Full : ButtonBrightness.Low);
if (!mRemove[ButtonXtoColX(x)])
greengrid[x, 7] = brightness;
else
redgrid[x, 7] = brightness;
}
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
mLaunchpadDevice[x, y].SetBrightness(redgrid[x, y], greengrid[x, y]);
if (mConfirmTime > 0)
mLaunchpadDevice.GetButton(ToolbarButton.Session).TurnOnLight();
else
mLaunchpadDevice.GetButton(ToolbarButton.Session).TurnOffLight();
if (mMode == 1)
mLaunchpadDevice.GetButton(ToolbarButton.Mixer).SetBrightness(ButtonBrightness.Full, ButtonBrightness.Off);
else
mLaunchpadDevice.GetButton(ToolbarButton.Mixer).SetBrightness(ButtonBrightness.Off, ButtonBrightness.Full);
if (mSoundType == 0) {
mLaunchpadDevice.GetButton(SideButton.SoundA).TurnOnLight();
mLaunchpadDevice.GetButton(SideButton.SoundB).TurnOffLight();
} else {
mLaunchpadDevice.GetButton(SideButton.SoundA).TurnOffLight();
mLaunchpadDevice.GetButton(SideButton.SoundB).TurnOnLight();
}
mLaunchpadDevice.GetButton(ToolbarButton.Up).TurnOnLight();
mLaunchpadDevice.GetButton(ToolbarButton.Down).TurnOnLight();
mLaunchpadDevice.GetButton(ToolbarButton.Left).TurnOnLight();
mLaunchpadDevice.GetButton(ToolbarButton.Right).TurnOnLight();
mLaunchpadDevice.GetButton(SideButton.Volume).TurnOnLight();
mLaunchpadDevice.GetButton(SideButton.Pan).TurnOnLight();
mLaunchpadDevice.GetButton(SideButton.Arm).TurnOnLight();
mLaunchpadDevice.Refresh();
Console.SetCursorPosition(0, 0);
for (int y = 0; y < NumRows; y++) {
for (int x = 0; x < NumCols; x++) {
if (mSequence[x, y])
Console.Write("X");
else
Console.Write(".");
}
Console.WriteLine();
}
}
}
}