using System;
using System.IO;
using System.Xml;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Diagnostics;
using ProjectMidiNS;
using System.Threading;
using MidiNS;
// A good 'event' for the TD8 is the Inc/Dec buttons
// The Inc/Dec buttons can be used to page forward through
// each page and song.
// Patches will be cached.
// When the song collection is loaded, the QuerySongs and CacheSongs
// will be fired, passing the SongCollection object. This allows
// each device to preload its patch files.
// When the request is received to select a patch, the filename will
// be compared, and reloaded if not equal. Otherwise the previously
// loaded data will be used.
namespace TD8NS
{
#region structs
// Define the data layout for the TD-8.
// Note: this is for the program use only, and may not align bit-for-bit with the
// actual TD-8 SysEx or internal layout.
//[StructLayout(LayoutKind.Sequential)]
public struct TD8Common
{
#region enums
public enum enumStudioType
{
Beach = 0,
Living,
Bath,
Studio,
Garage,
Locker,
Theater,
Cave,
Gym,
Stadium
};
public enum enumWallType
{
Wood = 0,
Plaster,
Glass
};
public enum enumRoomSize
{
Small = 1,
Medium,
Large
}
public enum enumEQLowFreq
{
Fo200Hz = 0,
Fo400Hz = 1
}
public enum enumEQHighFreq
{
Fo3kHz = 0,
Fo6kHz = 1
}
#endregion
#region variables
//[MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
private string name; // Max 8 characters allowed
private enumStudioType studioType;
private byte studioLevel;
private enumWallType wallType;
private enumRoomSize roomSize;
private enumEQLowFreq eqLowFreq;
private byte eqLowGain; // 0 - 24 (-12 to +12 dB)
private enumEQHighFreq eqHighFreq;
private byte eqHighGain; // 0 - 24 (-12 to +12 dB)
private bool ambienceOnOff;
private bool eqOnOff;
private bool brushOnOff;
private byte pedalHiHatVolume; // 0 - 15
private byte pedalBendRange; // 0-48 (-24 to +24 semitones)
private byte masterVolume; // 0 - 127
private byte ambienceGroupKitSendLevel; // 0 - 127
private byte ambienceGroupPercSendLevel; // 0 - 127
private byte ambienceGroupPartSendLevel; // 0 - 127
#endregion
#region Properties
public string Name
{
get { return name; }
set { name = value; }
}
public enumStudioType StudioType
{
get { return studioType; }
set { studioType = value; }
}
public byte StudioLevel
{
get { return studioLevel; }
set { studioLevel = value; }
}
public enumWallType WallType
{
get { return wallType; }
set { wallType = value; }
}
public enumRoomSize RoomSize
{
get { return roomSize; }
set { roomSize = value; }
}
public enumEQLowFreq EQLowFreq
{
get { return eqLowFreq; }
set { eqLowFreq = value; }
}
public byte EQLowGain // 0 - 24 (-12 to +12 dB)
{
get { return eqLowGain; }
set { eqLowGain = value; }
}
public enumEQHighFreq EQHighFreq
{
get { return eqHighFreq; }
set { eqHighFreq = value; }
}
public byte EQHighGain // 0 - 24 (-12 to +12 dB)
{
get { return eqHighGain; }
set { eqHighGain = value; }
}
public bool AmbienceOnOff
{
get { return ambienceOnOff; }
set { ambienceOnOff = value; }
}
public bool EQOnOff
{
get { return eqOnOff; }
set { eqOnOff = value; }
}
public bool BrushOnOff
{
get { return brushOnOff; }
set { brushOnOff = value; }
}
public byte PedalHiHatVolume // 0 - 15
{
get { return pedalHiHatVolume; }
set { pedalHiHatVolume = value; }
}
public byte PedalBendRange // 0-48 (-24 to +24 semitones)
{
get { return pedalBendRange; }
set { pedalBendRange = value; }
}
public byte MasterVolume // 0 - 127
{
get { return masterVolume; }
set { masterVolume = value; }
}
public byte AmbienceGroupKitSendLevel // 0 - 127
{
get { return ambienceGroupKitSendLevel; }
set { ambienceGroupKitSendLevel = value; }
}
public byte AmbienceGroupPercSendLevel // 0 - 127
{
get { return ambienceGroupPercSendLevel; }
set { ambienceGroupPercSendLevel = value; }
}
public byte AmbienceGroupPartSendLevel // 0 - 127
{
get { return ambienceGroupPartSendLevel; }
set { ambienceGroupPartSendLevel = value; }
}
#endregion
}
//[StructLayout(LayoutKind.Sequential)]
//
public class TD8PartialPad
{
#region variables
private uint instrument; // 0-1023
private int pitch; // 0-960 (-4800 - +4800 cent, 10 cent steps)
private byte decay; // 0-62 (-31 = +31)
private uint playPatternNumber; // 0-800 (0=off)
private byte gateTime; // 0-80 (0.1 second steps)
private byte noteNum; // 0-127
private bool padPatternVelocity; // 0-1
private byte level; // 0-127
private byte ambienceSendLevel; // 0-127
private bool pitchCtrlAssign; //
#endregion
#region Properties
public uint Instrument
{
get { return instrument; }
set { instrument = value; }
}
public int Pitch
{
get { return pitch; }
set { pitch = value; }
}
public byte Decay
{
get { return decay; }
set { decay = value; }
}
public uint PlayPatternNumber
{
get { return playPatternNumber; }
set { playPatternNumber = value; }
}
public byte GateTime
{
get { return gateTime; }
set { gateTime = value; }
}
public byte NoteNum // 0-127
{
get { return noteNum; }
set { noteNum = value; }
}
public bool PadPatternVelocity // 0-1
{
get { return padPatternVelocity; }
set { padPatternVelocity = value; }
}
public byte Level // 0-127
{
get { return level; }
set { level = value; }
}
public byte AmbienceSendLevel // 0-127
{
get { return ambienceSendLevel; }
set { ambienceSendLevel = value; }
}
public bool PitchCtrlAssign
{
get { return pitchCtrlAssign; }
set { pitchCtrlAssign = value; }
}
#endregion
}
//public struct TD8Pad
public class TD8Pad
{
public enum enumShellDepth
{
Normal = 0,
Deep = 1,
Deep1 = 1,
Deep2 = 2,
Deep3 = 3,
Deep4 = 4
}
public enum enumHeadType
{
Clear = 0,
Coated = 1,
PinStripe = 2
}
public enum enumMuffling
{
Off = 0,
Tape1 = 1, // Kick
Tape2 = 2, // Kick
Blanket = 3, // Kick
Doughnuts1 = 3, // Snare
Felt1 = 3, // Tom
Weight = 4, // Kick
Doughnuts2 = 4, // Snare
Felt2 = 4 // Tom
}
public enum enumStrainerAdjustment
{
Off = 0,
Loose,
Medium,
Tight
}
//[MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
public TD8PartialPad[] Pad; // was Head
//public TD8PartialPad Head;
//public TD8PartialPad Rim;
private byte pan;
private enumShellDepth shellDepth;
private enumHeadType headType;
private enumMuffling muffling;
private enumStrainerAdjustment strainerAdjustment;
public TD8Pad()
{
Pad = new TD8PartialPad[2];
Pad[0] = new TD8PartialPad();
Pad[1] = new TD8PartialPad();
//Head = new TD8PartialPad();
//Rim = new TD8PartialPad();
}
public byte Pan
{
get { return pan; }
set { pan = value; }
}
public enumShellDepth ShellDepth
{
get { return shellDepth; }
set { shellDepth = value; }
}
public enumHeadType HeadType
{
get { return headType; }
set { headType = value; }
}
public enumMuffling Muffling
{
get { return muffling; }
set { muffling = value; }
}
public enumStrainerAdjustment StrainerAdjustment
{
get { return strainerAdjustment; }
set { strainerAdjustment = value; }
}
}
public class TD8Kit
{
public const int NumPads = 12;
public TD8Common Common = new TD8Common();
public TD8Pad[] Pads = new TD8Pad[NumPads]; // 12 pads per kit
public TD8Kit()
{
for(int x=0; x<NumPads; x++) Pads[x] = new TD8Pad();
}
}
#endregion
/// <summary>
/// This class implements the TD8 MIDI device.
/// </summary>
[ProjectMidiAssemblyAttribute(AssemblyType.Device, "TD8" )]
public class TD8 : IProjectMidi, IProjectMidiHideShow
{
#region Constants
const string name = "TD8";
const int DefaultKitNum = 63; // The top kit #64 is the default kit.
const int DevNum = 0x10;
const int DevMidiChan = 9; // Midi channel 10 (0 based)
const int patchCommonLength = 25;
const int patchPadLength = 43;
public const int NumGroups = 16;
public const int NumInstruments = 1025;
const byte EOX = 0xf7;
//public const string RegistryPath = @"Software\ProjectMidi\MidiDevices";
//const string TD8TemplateSysExFilePathKey = "TD8TemplateSysExFilePath";
//const string TD8SysExFilesDirKey = "TD8SysExFilesDir";
const string TD8FolderName = "TD8";
const int SysExPrefixLen = 10; // SysEx prefix (f0, 41, dev, 00, 20, 12, aa, aa, aa, aa)
const int NumSysExCommonBytes = 37; // 'Common' parameters size (SysExPrefixLen + 25 + chksum + 0xf7)
const int NumSysExPadBytes = 55;
const int BassDrumNoteNum = 36;
const int SnareDrumNoteNum = 38;
const int SnareDrumRimNoteNum = 40;
const int HighHatNoteNum = 46;
const int HighTomNoteNum = 48;
const int MidTomNoteNum = 45;
const int LowTomNoteNum = 41;
const int FloorTomNoteNum = 31;
const int CrashCymbalNoteNum = 49;
const int SplashCymbalNoteNum = 57;
const int RideCymbalNoteNum = 51;
const int CowbellNoteNum = 32;
public const int KickPadIndex = 0;
public const int Kick2PadIndex = 1;
public const int SnarePadIndex = 2;
public const int Tom1PadIndex = 3;
public const int Tom2PadIndex = 4;
public const int Tom3PadIndex = 5;
public const int Tom4PadIndex = 10;
public const int HihatPadIndex = 6;
public const int CrashPadIndex = 7;
public const int SplashPadIndex = 8;
public const int RidePadIndex = 9;
public const int CowbellPadIndex = 11;
#endregion
#region Instrument name arrays
#region vkickGroup 1-90
public static string[] vkickGroup = { // 1 - 90
"Dbl Head Kick",
"Sharp Kick",
"Acoustic Kick",
"Meat Kick",
"R8 Low Kick",
"R8 Dry Kick",
"WD Beater Kick",
"Open Kick",
"Vintage Kick",
"26 Deep Kick", // 10
"Thick Hd Kick",
"Round Kick",
"Medium Kick",
"Big Room Kick",
"Big Kick",
"Big Low Kick",
"Studio 1 Kick",
"Studio 2 Kick",
"Studio 3 Kick",
"Studio 4 Kick", // 20
"Studio 5 Kick",
"Studio 6 Kick",
"Studio 7 Kick",
"Studio 8 Kick",
"Buzz 1 Kick",
"Buzz 2 Kick",
"Buzz 3 Kick",
"Buzz 4 Kick",
"Buzz 5 Kick",
"Room 1 Kick", // 30
"Room 2 Kick",
"Room 3 Kick",
"Room 4 Kick",
"Room 5 Kick",
"Room 6 Kick",
"Room 7 Kick",
"Amb 1 Kick",
"Amb 2 Kick",
"Amb 3 Kick",
"Amb 4 Kick", // 40
"Solid 1 Kick",
"Solid 2 Kick",
"Solid 3 Kick",
"Jazz 1 Kick",
"18 Jazz Kick",
"Brush Hit Kick",
"Wood 1 Kick",
"Wood 2 Kick",
"Wood 3 Kick", // 50
"Wood 4 Kick",
"Maple 1 Kick",
"Maple 2 Kick",
"Oak Kick",
"Birch Kick",
"Rose Wood Kick",
"One Ply Kick",
"Oyster Kick",
"Dry Kick",
"Dry Medium Kick", // 60
"Dry Hard Kick",
"Deep Dry Kick",
"Fusion Kick",
"Sand Bag Kick",
"BasketBall Kick",
"Mondo Kick",
"MdVrb1 Kick",
"MdVrb2 Kick",
"Sizzle Kick",
"Box Kick", // 70
"Ninja Kick",
"Dance Kick",
"House Kick",
"Pillow Kick",
"Rap Kick",
"TR808 Kick",
"808 Hard Kick",
"808 Boom Kick",
"808 Noise Kick",
"TR909 Kick", // 80
"909 Wood Kick",
"909 HdatKick",
"Elephant Kick",
"Cattle Kick",
"Door Kick",
"Punch Kick",
"Machine Kick",
"Broken Kick",
"Bend Up Kick",
"Hard Noise Kick" // 90
};
#endregion
#region kickGroup 91-129
public static string[] kickGroup = { // 91 - 129
"R8 Solid Kick",
"R8 Solid Kick",
"Thin Head Kick",
"Tight Kick",
"Chunk Kick",
"Gate Kick",
"Giant Kick",
"Inside Kick",
"Std1 1 Kick",
"Std1 2 Kick",
"Std2 1 Kick", // 100
"Std2 2 Kick",
"Room 8 Kick",
"Room 9 Kick",
"Power Kick 1",
"Power Kick 2",
"Jazz 3 Kick",
"Jazz 4 Kick",
"Brush Kick",
"Elec 1 Kick",
"Elec 2 Kick", // 110
"ElBend Kick",
"Plastic 1 Kick",
"Plastic 2 Kick",
"Gabba Kick",
"Gabba2 Kick",
"Tail Kick",
"Jungle Kick",
"HipHop Kick",
"LoFi 1 Kick",
"LoFi 2 Kick", // 120
"LoFi 3 Kick",
"LoFi 4 Kick",
"Noisy Kick",
"Splat Kick",
"Scratch 1 Kick",
"Scratch 2 Kick",
"Hi-Q Kick",
"Space Kick",
"Syn Bass Kick" // 129
};
#endregion
#region vsnareGroup 130-235
public static string[] vsnareGroup = { // 130 - 235
"Custom Snare (pos)", // 130
"Cstm Rimshot",
"CstmBr S(pos)",
"CstmBrRS",
"CstmSt S(pos)",
"CstmStRS",
"Picolo1S(pos)",
"Pco1 RS",
"Pco1BR S(pos)",
"Pco1BrRS",
"Pco1St S(pos)", // 140
"Pco1StRS",
"Picolo2S(pos)",
"Pco2 RS",
"Pco2Br S(pos)",
"Pco2BrRs",
"Pco2St S(pos)",
"Pco2StRs",
"Picolo3S(pos)",
"Pco3 RS",
"Pco3Br S(pos)", // 150
"Pco3BrRs",
"Pco3St S(pos)",
"Pco3StRs",
"Medium1S(pos)",
"Med1 RS",
"Med1 XS(x-stick)",
"Med1Br S(pos)",
"Med1BrRS",
"Med1BrXS(x-stick)",
"Med1St S(pos)", // 160
"Med1StRS",
"Med1StXS(x-stick)",
"Medium2S(pos)",
"Med2 RS",
"Med2Br S(pos)",
"Med2BrRS",
"Med2St S(pos)",
"Med2StRS",
"Medium3S(pos)",
"Med3 RS", // 170
"Med3Br S(pos)",
"Med3BrRS",
"Med3St S(pos)",
"Med3StRS",
"Medium4S(pos)",
"Med4 RS",
"Med4Br S(pos)",
"Med4BrRS",
"Med4St S(pos)",
"Med4StRS", // 180
"Fat1 S(pos)",
"Fat1 RS",
"Fat1Br S(pos)",
"Fat1BrRS",
"Fat1St S(pos)",
"Fat1StRS",
"Fat2 S(pos)",
"Fat2 RS",
"Fat2Br S(pos)",
"Fat2BrRS", // 190
"Fat2St S(pos)",
"Fat2StRS",
"AcusticS(pos)",
"Acus RS",
"AcusBr S(pos)",
"AcusBrRS",
"AcusSt S(pos)",
"AcusStRS",
"VintageS(pos)",
"Vntg RS", // 200
"VntgBr S(pos)",
"VntgBrRS",
"VntgSt S(pos)",
"VntgStRS",
"Comp S(pos)",
"Comp RS",
"CompBr S(pos)",
"CompBrRS",
"CompSt S(pos)",
"CompStRS", // 210
"Jazz S",
"Jazz RS",
"Jazz XS(x-stick)",
"JazzBr S",
"JazzBrRS",
"JazzBrXS(x-stick)",
"JazzSt S",
"JazzStRS",
"JazzStXS(x-stick)",
"Dirty S(pos)", // 220
"Drty RS",
"DrtyBr S(pos)",
"DrtyBrRS",
"DrtySt S(pos)",
"DrtyStRS",
"13 S",
"13 RS",
"Birch S",
"Birch RS",
"TD7Mpl S", // 230
"TD7MplRS",
"Ballad S",
"Brush1 S(sweep)",
"Brush2 S(sweep)",
"Brush3 S(sweep)"
};
#endregion
#region snareGroup 236-324
public static string[] snareGroup = { // 236 - 324
"Brush Tap",
"Brush Slap",
"Brush Swirl",
"Brush TMB Snare *sweep",
"MIDI Brush 1 Snare", //240
"MIDI Brush 2 Snare",
"MIDI Brush 3 Snare",
"Boston Snare",
"Boston RimShot",
"Bronze Snare",
"Bronze RimShot",
"Bronze 2 Snare",
"Bronze 2 RimShot",
"Birch 2 Snare",
"Copper Snare", // 250
"Copper 2 Snare",
"10 inch Snare",
"L.A. Snare",
"London Snare",
"Ring Snare",
"Ring Rimshot",
"Rock Snare",
"Rock RimShot",
"R8 Maple Snare",
"R8 Maple RimShot", // 260
"Bigshot Snare",
"Standard1 1 Snare",
"Standard1 2 Snare",
"Standard2 1 Snare",
"Standard2 2 Snare",
"Room 1 Snare",
"Room 2 Snare",
"Power 1 Snare",
"Power 2 Snare",
"Gate Snare", // 270
"Jazz 2 Snare",
"Jazz 3 Snare",
"Funk Snare",
"Funk RimShot",
"Bop Snare",
"Bop RimShot",
"Picolo 5 Snare",
"Picolo 5 RimShot",
"Picolo 6 Snare",
"Picolo 6 RimShot", // 280
"Medium 5 Snare",
"Medium 5 RimShot",
"Medium 6 Snare",
"Medium 6 RimShot",
"Medium 7 Snare",
"Medium 7 RimShot",
"Medium 8 Snare",
"Medium 8 RimShot",
"Fat 3 Snare",
"Fat 3 RimShot", // 290
"Fat 4 Snare",
"Fat 4 RimShot",
"Dynamic Snare",
"Dynamic RimShot",
"Roll Snare",
"Buzz Snare",
"Dopin 1 Snare",
"Dopin 2 Snare",
"Raggae Snare",
"Cruddy Snare", // 300
"Dance 1 Snare",
"Dance 2 Snare",
"House Snare",
"House DPN Snare",
"Clap! Snare",
"Whack Snare",
"TR808 Snare",
"TR909 Snare",
"Electric 1 Snare",
"Electric 2 Snare", // 310
"Electric 3 Snare",
"El Noise Snare",
"Hip Hop Snare",
"Hip Hop 2 Snare",
"LoFi Snare",
"LoFi RimShot",
"Radio Snare",
"Cross-Stick 1",
"Cross-Stick 2",
"Cross-Stick 3", // 320
"Cross-Stick 4",
"Cross-Stick 5",
"Cross-Stick 6",
"808 Cross-Stick"
};
#endregion
#region vtomGroup 325-484
public static string[] vtomGroup = { // 325 - 484
"Oyster Tom1",
"Oyster Tom2",
"Oyster Tom3",
"Oyster Tom4",
"Comp Tom1",
"Comp Tom2", // 330
"Comp Romp3",
"Comp Tom4",
"Fibre Tom1",
"Fibre Tom2",
"Fibre Tom3",
"Fibre Tom4",
"Dry 1 Tom1",
"Dry 1 Tom2",
"Dry 1 Tom3",
"Dry 1 Tom4", // 340
"Dry 2 Tom1",
"Dry 2 Tom2",
"Dry 2 Tom3",
"Dry 2 Tom4",
"Maple Tom1",
"Maple Tom2",
"Maple Tom3",
"Maple Tom4",
"Rose Tom1",
"Rose Tom2", // 350
"Rose Tom3",
"Rose Tom4",
"Sakura Tom1",
"Sakura Tom2",
"Sakura Tom3",
"Sakura Tom4",
"Jazz 1 Tom1",
"Jazz 1 Tom2",
"Jazz 1 Tom3",
"Jazz 1 Tom4", // 360
"Jazz 2 Tom1",
"Jazz 2 Tom2",
"Jazz 2 Tom3",
"Jazz 2 Tom4",
"Buzz 1 Tom1",
"Buzz 1 Tom2",
"Buzz 1 Tom3",
"Buzz 1 Tom4",
"Buzz 2 Tom1",
"Buzz 2 Tom2", // 370
"Buzz 2 Tom3",
"Buzz 2 Tom4",
"Buzz 3 Tom1",
"Buzz 3 Tom2",
"Buzz 3 Tom3",
"Buzz 3 Tom4",
"Buzz 4 Tom1",
"Buzz 4 Tom2",
"Buzz 4 Tom3",
"Buzz 4 Tom4", // 380
"Natural Tom1",
"Natural Tom2",
"Natural Tom3",
"Natural Tom4",
"Natural 2 Tom1",
"Natural 2 Tom2",
"Natural 2 Tom3",
"Natural 2 Tom4",
"Studio Tom1",
"Studio Tom2", // 390
"Studio Tom3",
"Studio Tom4",
"Slap Tom1",
"Slap Tom2",
"Slap Tom3",
"Slap Tom4",
"Room 1 Tom1",
"Room 1 Tom2",
"Room 1 Tom3",
"Room 1 Tom4", // 400
"Room 2 Tom1",
"Room 2 Tom2",
"Room 2 Tom3",
"Room 2 Tom4",
"Room 3 Tom1",
"Room 3 Tom2",
"Room 3 Tom3",
"Room 3 Tom4",
"Room 4 Tom1",
"Room 4 Tom2", // 410
"Room 4 Tom3",
"Room 4 Tom4",
"Room 5 Tom1",
"Room 5 Tom2",
"Room 5 Tom3",
"Room 5 Tom4",
"Big Tom1",
"Big Tom2",
"Big Tom3",
"Big Tom4", // 420
"Rock Tom1",
"Rock Tom2",
"Rock Tom3",
"Rock Tom4",
"Punch Tom1",
"Punch Tom2",
"Punch Tom3",
"Punch Tom4",
"Oak Tom1",
"Oak Tom2", // 430
"Oak Tom3",
"Oak Tom4",
"Balsa Tom1",
"Balsa Tom2",
"Balsa Tom3",
"Balsa Tom4",
"Vintage Tom1",
"Vintage Tom2",
"Vintage Tom3",
"Vintage Tom4", // 440
"Brush 1 Tom1",
"Brush 1 Tom2",
"Brush 1 Tom3",
"Brush 1 Tom4",
"Brush 2 Tom1",
"Brush 2 Tom2",
"Brush 2 Tom3",
"Brush 2 Tom4",
"Dark Tom1",
"Dark Tom2", // 450
"Dark Tom3",
"Dark Tom4",
"Attack Tom1",
"Attack Tom2",
"Attack Tom3",
"Attack Tom4",
"Hall Tom1",
"Hall Tom2",
"Hall Tom3",
"Hall Tom4", // 460
"Birch Tom1",
"Birch Tom2",
"Birch Tom3",
"Birch Tom4",
"Beechnut Tom1",
"Beechnut Tom2",
"Beechnut Tom3",
"Beechnut Tom4",
"Micro Tom1",
"Micro Tom2", // 470
"Micro Tom3",
"Micro Tom4",
"Bend Tom1",
"Bend Tom2",
"Bend Tom3",
"Bend Tom4",
"Bowl Tom1",
"Bowl Tom2",
"Bowl Tom3",
"Bowl Tom4", // 480
"Dirty Tom1",
"Dirty Tom2",
"Dirty Tom3",
"Dirty Tom4"
};
#endregion
#region tomGroup 485-560
public static string[] tomGroup = // 485 - 560
{
"Standard 1 Tom1",
"Standard 1 Tom2",
"Standard 1 Tom3",
"Standard 1 Tom4",
"Standard 1 Tom5",
"Standard 1 Tom6", // 490
"Standard 2 Tom1",
"Standard 2 Tom2",
"Standard 2 Tom3",
"Standard 2 Tom4",
"Standard 2 Tom5",
"Standard 2 Tom6",
"Room 6 Tom1",
"Room 6 Tom2",
"Room 6 Tom3",
"Room 6 Tom4", // 500
"Room 6 Tom5",
"Room 6 Tom6",
"Power Tom1",
"Power Tom2",
"Power Tom3",
"Power Tom4",
"Power Tom5",
"Power Tom6",
"Jazz 3 Tom1",
"Jazz 3 Tom2", // 510
"Jazz 3 Tom3",
"Jazz 3 Tom4",
"Jazz 3 Tom5",
"Jazz 3 Tom6",
"Brush 3 Tom1",
"Brush 3 Tom2",
"Brush 3 Tom3",
"Brush 3 Tom4",
"Brush 3 Tom5",
"Brush 3 Tom6", // 520
"Gate Tom1",
"Gate Tom2",
"Gate Tom3",
"Gate Tom4",
"LoFi Tom1",
"LoFi Tom2",
"LoFi Tom3",
"LoFi Tom4",
"Elec Bend Tom1",
"Elec Bend Tom2", // 530
"Elec Bend Tom3",
"Elec Bend Tom4",
"Elec Bend 2 Tom1",
"Elec Bend 2 Tom2",
"Elec Bend 2 Tom3",
"Elec Bend 2 Tom4",
"Elec Bend 3 Tom1",
"Elec Bend 3 Tom2",
"Elec Bend 3 Tom3",
"Elec Bend 3 Tom4", // 540
"Elec Noise Tom1",
"Elec Noise Tom2",
"Elec Noise Tom3",
"Elec Noise Tom4",
"Elec Dual Tom1",
"Elec Dual Tom2",
"Elec Dual Tom3",
"Elec Dual Tom4",
"Elec Tom1",
"Elec Tom2", // 550
"Elec Tom3",
"Elec Tom4",
"Elec Tom5",
"Elec Tom6",
"TR808 Tom1",
"TR808 Tom2",
"TR808 Tom3",
"TR808 Tom4",
"TR808 Tom5",
"TR808 Tom6" // 560
};
#endregion
#region hihatGroup 561-598
public static string[] hihatGroup = // 561 - 598
{
"Pure Hihat",
"PureEGHihat",
"BrightHihat",
"BriteGHihat",
"Jazz Hihat",
"HazzEGHihat",
"Thin Hihat",
"ThinEGHihat",
"Heavy Hihat",
"HevyEGHihat", // 570
"Light Hihat",
"LigtEGHihat",
"Dark Hihat",
"DarkEGHihat",
"12 Hihat",
"12 EG Hihat",
"13 Hihat",
"13 EG Hihat",
"14 Hihat",
"14 EG Hihat", // 580
"15 Hihat",
"15 EG Hihat",
"Brush 1 Hihat",
"Brush 2 Hihat",
"Sizzle Hihat",
"Sizzle 2 Hihat",
"Voice Hihat",
"HandC Hihat",
"Tambarine Hihat",
"Maracas Hihat", // 590
"TR808 Hihat",
"TR909 Hihat",
"CR78 Hihat",
"Metal 808 Hihat",
"Metal 909 Hihat",
"Metal78 Hihat",
"LoFi1 Hihat",
"LoFi2 Hihat"
};
#endregion
#region crashGroup 599-634
public static string[] crashGroup = // 599 - 634
{
"Medium 14 Crash",
"Medium 16 Crash", // 600
"Mediuim 18 Crash",
"Quick 16 Crash",
"Quick 18 Crash",
"Thin 16 Crash",
"Thin 18 Crash",
"Brush 1 Crash",
"Brush 2 Crash",
"Sizzle Brush Crash",
"Swell Crash",
"Splash 6", // 610
"Splash 8",
"Splash 10",
"Splash 12",
"Cup 4",
"Cup 6",
"Hand Splash 8",
"Hand Splash 10",
"China 10",
"China 12",
"China 18", // 620
"China 20",
"Sizzle China",
"Swell China",
"PGYZBACK",
"Pgy Crash 1",
"Pgy Crash 2",
"Pgy Crash 3",
"Pg Splash 1",
"Pg Splash 2",
"Phase Cymbal", // 630
"Elec Crash",
"TR808 Crash",
"LoFi 1 Crash",
"LoFi 2 Crash"
};
#endregion
#region rideGroup 635-679
public static string[] rideGroup = // 635 - 679
{
"Jazz Ride",
"Jazz Ride Edge",
"Jazz Ride Bell",
"Jazz Ride X (edge/bell)",
"Pop Ride",
"Pop Ride Edge", // 640
"Pop Ride Bell",
"Pop Ride X (edge/bell)",
"Rock Ride",
"Rock Ride Edge",
"Rock Ride Bell",
"Rock Ride X (edge/bell)",
"Lite Ride",
"Lite Ride Edge",
"Lite Ride Bell",
"Lite Ride X (edge/bell)", //650
"Crash Ride",
"Crash Ride Edge",
"Dark Crash Ride",
"Dark Crash Ride Edge",
"Brush 1 Ride",
"Brush 2 Ride",
"Sizzle Brush Ride",
"Sizzle 1 Ride",
"Sizzle 1 Ride Edge",
"Sizzle 1 Ride Bell", // 660
"Sizzle 1 Ride X (edge/bell)",
"Sizzle 2 Ride",
"Sizzle 2 Ride Edge",
"Sizzle 2 Ride Bell",
"Sizzle 2 Ride X (edge/bell)",
"Sizzle 3 Ride",
"Sizzle 3 Ride Edge",
"Sizzle 3 Ride Bell",
"Sizzle 3 Ride X (edge/bell)",
"Sizzle 4 Ride", // 670
"Pigmy Ride 1",
"Pigmy Ride 1 Bell",
"Pigmy Ride 1 X (edge/bell)",
"Pigmy Ride 2",
"Pigmy Ride 2 Bell",
"Pigmy Ride 2 X (edge/bell)",
"LoFi Ride",
"LoFi Ride Edge",
"LoFi Ride Bell"
};
#endregion
#region percGroup 680-810
public static string[] percGroup = // 680 - 810
{
"R8 Bongo Hi",
"R8 Bongo Lo",
"R8 Bongo 2 Hi",
"R8 Bongo 2 Lo",
"Bongo Hi",
"Bongo Lo",
"Bongo 2 Hi",
"Bongo 2 Lo",
"R8 Conga Mt",
"R8 Conga Hi",
"R8 Conga Lo", // 690
"Conga Mt",
"Conga Sl",
"Conga Op",
"Conga Lo",
"Conga Mt Vs",
"Conga Sl Vs",
"Cowbell 1",
"Cowbell 2",
"Cowbell Duo",
"Claves", // 700
"Guiro Long 1",
"Guiro Short",
"Guiro Long 2",
"Guiro Vs",
"Maracas",
"Shaker",
"Small Shaker",
"Tambarine",
"Tambarine 2",
"Tambarine 3", // 710
"Tambarine 4",
"Timbale Hi",
"Timbale Rm",
"Timbale Lo",
"Paila",
"Timbale 2 Hi",
"Timbale 2 Lo",
"Vibraslap",
"Agogo Hi",
"Agogo Lo", // 720
"Agogo 2 Hi",
"Agogo 2 Lo",
"Cabasa Up",
"Cabasa Down",
"Cabasa Vs",
"Cuica Mt 1",
"Cuica Up",
"Cuica Lo",
"Cuica Mt 2",
"Pandro Mt", // 730
"Pandroop",
"Pandro Sl",
"Pandro Vs",
"Surdoh Mt",
"Surdoh P",
"Surdoh Vs",
"Surcol Mt",
"Surdol Op",
"Surdol Vs",
"Whistle", // 740
"Whistle Sh",
"Caxixi",
"Tabla Na",
"Tabla Tin",
"Tabla Un",
"Tabla Te",
"Tabla Ti",
"Baya Ge",
"Baya Ka",
"Baya Gin", // 750
"Baya Sld",
"Pot Drum",
"Pot Drum Mt",
"Pot Drum Vs",
"Talkin Drum",
"Thai Gong",
"Thai Gong 2",
"Bell Tree",
"Tiny Gong",
"Gong", // 760
"Temple Bell",
"Wa-Daiko",
"Taiko",
"Sleigh bell",
"Tree Chime",
"Triangle Op",
"Triangle Mt",
"Triangle Vs",
"R70 Trio P",
"R70 Tri Mt", // 770
"R70 Tri Vs",
"Castanet",
"Wood Block Hi",
"Wood Block Lo",
"Concert Bd",
"Concert Bd Mt",
"Hand Cymbal",
"Hand Cymbal Mt",
"Timpani G",
"Timpani C", // 780
"Timpani E",
"Perc Hit 1",
"Perc Hit 2",
"Orch Maj",
"Orch Min",
"Orch Dim",
"Kick/roll",
"Kick/Cymbal",
"Orch Roll",
"Orch Chok", // 790
"Hit Roll",
"Finale",
"808 Clap",
"808 Cowbell 1",
"808 Cowbell 2",
"808 Maracas",
"808 Claves",
"808 Conga",
"909 Rim",
"909 Clap", // 800
"78 Cowbell",
"78 Guiro",
"78 Guiro St",
"78 Maracas",
"78 M Beat",
"78 Tambarine",
"78 Bongo",
"78 Claves",
"78 Rim",
"55 Claves" // 810
};
#endregion
#region specialGroup 811-888
public static string[] specialGroup = // 811 - 888
{
"Applause",
"Encore",
"Bird",
"Dog",
"Bubbles",
"Heart Beat",
"Telephone",
"Punch",
"Kung Foo",
"Pistol", // 820
"Gun Shot",
"Glass",
"Hammer",
"Bucket",
"Barrel",
"Trashcan",
"AF Stomp",
"Bounce",
"Cuica Hit",
"Monster", // 830
"Airdrive",
"Car Door",
"Car Cell",
"Car Engine",
"Car Horn",
"Helicopter",
"Thunder",
"Bomb",
"Sticks",
"Click", // 840
"Tamb FX",
"TEK Click",
"Beep Hi",
"Beep Lo",
"Metro Bell",
"Metro Click",
"Snaps",
"Clap",
"Noise Clap",
"Tek Noise", // 850
"Metal Slap",
"R8 Slap",
"Vocoder 1",
"Vocoder 2",
"Vocoder 3",
"Dyn Scratch",
"Scratch 1",
"Scratch 2",
"Scratch 3",
"Scratch 4", // 860
"Scratch 5",
"Scratch 6",
"Scratch Loop",
"Phil Hit",
"LoFi Hit",
"Hi-Q",
"Hoo...",
"DAO Drill",
"Scrape",
"Martian", // 870
"CoroCoro",
"Coro Bend",
"Burt",
"Boing 1",
"Boing 2",
"Tekno Bird",
"Nantoka!",
"Elec Bird",
"Metal Bend 1",
"Metal Bend 2", // 880
"Metal Noise",
"Metal Phase",
"Laser",
"Mystery",
"Time Trip",
"Kick Amb",
"Snare Amb",
"Tom Amb" // 888
};
#endregion
#region melodicGroup 889-920
public static string[] melodicGroup = // 889 - 920
{
"Kalimba",
"Steel Drum", // 890
"Glockenspeil",
"Vibraphone",
"Marimba",
"Xylophone",
"Tubular Bell",
"Celesta",
"Saw Wave",
"Tb Bass",
"Slap Bass",
"Guitar Slide", // 900
"Guitar Scratch",
"Guitar Dist",
"Guitar Bs 1",
"Guitar Bs 2",
"Cut Guitar Down",
"Cut Guitar Up",
"Fret Noise",
"Bass Slide",
"Wah Guitar Down 1",
"Wah Guitar Up 1", // 910
"Wah Guitar Down 2",
"Wah Guitar Up 2",
"Shami Vs",
"Brass Vs",
"Strings Vs",
"Pizicato",
"Tekno Hit",
"Funk Hit 1",
"Funk Hit 2",
"Func Hit 3" // 920
};
#endregion
#region voiceGroup 921-971
public static string[] voiceGroup = // 921 - 971
{
"Lady Ahh",
"Aoouu!",
"Hooh!",
"Haa!",
"Say Yeah!",
"Yeah",
"Ahhh",
"Haaa",
"Achaa!",
"Nope!", // 930
"Bap",
"Dat",
"BapDat Vs",
"Doot",
"DAO Fall 1",
"DAO Fall 2",
"DAO Fall 3",
"DAO Fall 4",
"DoDat Vs",
"DoDao Vs",
"Scat 1 Vs",
"Scat 2 Vs",
"Scat 3 Vs",
"Scat 4 Vs",
"Scat 5 Vs",
"Voice K",
"Voice Ok",
"Voice S",
"Voice T1",
"Voice T2",
"Voice T3",
"Voice T4",
"Voice Cr",
"Count 1",
"Count 2",
"Count 3",
"Count 4",
"Count 5",
"Count 6",
"Count 7",
"Count 8",
"Count 9",
"Count 10",
"Count 11",
"Count 12",
"Count 13",
"Count And",
"Count E",
"Count A",
"Count Ti",
"Count Ta"
};
#endregion
#region reverseGroup 972-989
public static string[] reverseGroup = // 972 - 989
{
"Reverse Kick 1",
"Reverse Kick 2",
"Reverse Snare 1",
"Reverse Snare 2",
"Reverse Tom",
"Reverse Crash 1",
"Reverse Crash 2",
"Reverse China",
"Reverse Bell Tree", // 980
"Reverse Hi-Q",
"Reverse MFaze",
"Reverse Air Dr",
"Reverse Boing 1",
"Reverse Boing 2",
"Reverse Bend",
"Reverse Vocoder",
"Reverse Carcl",
"Reverse Car Engine"
};
#endregion
#region fixedhhGroup 990-1023
public static string[] fixedhhGroup = // 990 - 1023
{
"Standard Closed HH", // 990
"Standard 1 Edge Closed HH",
"Standard 1 Open HH",
"Standard 1 Edge Open HH",
"Standard 1 Pedal HH",
"Standard 2 Closed HH",
"Standard 2 Edge Closed HH",
"Standard 2 Open HH",
"Pedal HH",
"Room Closed HH",
"Room Edge Closed HH", // 1000
"Room Open HH",
"Room Edge Open HH",
"Room Pedal HH",
"Power Closed HH",
"Power Edge Closed HH",
"Power Open HH",
"Power Pedal HH",
"Brush Closed HH",
"Brush Edge Closed HH",
"Brush Open HH",
"Brush Pedal HH",
"Elec Closed HH",
"Elec Open HH",
"Elec Pedal HH",
"808 Closed HH",
"808 Edge Closed HH",
"808 Open HH",
"808 Edge Open HH",
"808 Pedal HH",
"LoFi Closed HH",
"LoFi Open HH",
"LoFi Edge Open HH",
"LoFi Pedal HH"
};
#endregion
#region offGroup 1024-1024
public static string[] offGroup = { "Off" }; // 1024
#endregion
#region instGroups
public static string[] nodeNames =
{
"V-Kick Group",
"Kick Group",
"V-Snare Drums",
"Snare Drums",
"V-Tom Group",
"Tom Group",
"Hi-Hat Group",
"Crash Cymbal Group",
"Ride Cymbal Group",
"Percussion Group",
"Special Group",
"Melodic Group",
"Voice Group",
"Reverse Group",
"Fixed Hi-Hat Group",
"Off Group"
};
public static string[][] instGroupNames = new string[NumGroups][];
public static string[] instrumentNames = new string[NumInstruments];
#endregion
#endregion
#region member variables
private MidiChannelMap inputChannelMap = new MidiChannelMap();
private MidiChannelMap outputChannelMap = new MidiChannelMap();
internal int currentKitNum = 0;
private IProjectMidiParent projectMidiParent = null;
private ISongSet isongset;
private IIProjectMidiCollection iprojectmidis;
private string TD8TemplateSysExFilePath;
private string TD8Folder;
private string currentFileName;
private int numKits;
public TD8Kit[] kits;
private bool dirtyFlag = false;
//private bool templateDirtyFlag = false;
private TD8Edit frm = null;
[ProjectMidiEventAttribute("Inc/Dec",128,"SongNum",ConnectionType.Normal,"Send the program number whenever it changes. This can be caused by the Inc/Dec buttons.")]
public event ProjectMidiEventHandler OnIncDecDevInput;
[ProjectMidiEventAttribute("Cowbell",128,"",ConnectionType.Normal,"Sent whenever the Cowbell is struck.")] // No default
public event ProjectMidiEventHandler OnCowBellDevInput;
#endregion
#region Actions
[ProjectMidiActionAttribute("CacheSongs",1,"CacheSongs","System calls this to sync song information.")]
public void OnCacheSongs( object source, EventArgs e )
{
ObjectEventArgs eObj = e as ObjectEventArgs;
Debug.Assert(eObj!=null,"TD8 OnCacheSongs error: e is not an ObjectEventArgs");
if(eObj==null) return;
ISongCollection isongs = eObj.obj as ISongCollection;
Debug.Assert(isongs!=null,"TD8 OnCacheSongs error: e is not an ISongCollection");
Console.WriteLine("TD8 OnCacheSongs, # songs = {0}",isongs.Count);
//Debug.Assert(ie.data < 64,"TD8 OnNumSongsChanged error: # songs too big: "+ie.data);
int songnum = 0;
foreach(ISong song in isongs)
{
int pagenum = 0;
foreach(IPage page in song.Pages)
{
SetOrCachePatch(song.Name,songnum,pagenum,0);
pagenum++;
IPage donothing = page; // Eliminate warning message, that's all
}
songnum++;
}
}
[ProjectMidiActionAttribute("Song#",128,"SongNum","Selects the song number from the current set. TD8 patches for that song will be loaded.")]
void OnSongNumChanged( object sender, EventArgs e )
{
IntEventArgs ie = e as IntEventArgs;
Debug.Assert(ie!=null,"TD8 OnSongNumChanged error: e is not an IntEventArgs");
if(ie==null) return;
Debug.Assert(ie.data < isongset.Songs.Count,"TD8: OnSongNumChanged error. Song # too big: "+ie.data);
SetOrCachePatch(isongset.Songs.Item(ie.data).Name,ie.data,isongset.CurrentPageNum,isongset.CurrentPatchNum);
currentFileName = Path.Combine(TD8Folder,Path.GetFileNameWithoutExtension(isongset.Songs.Item(ie.data).Name)+".TD8");
currentKitNum = ie.data;
Console.WriteLine("SetPatch writing program change {0}",currentKitNum);
MidiOut( new MidiData( (byte)(MidiStatus.ProgramChange+DevMidiChan),(byte)currentKitNum,0),0);
}
[ProjectMidiActionAttribute("Page#",128,"PageNum","Selects the page number for the current song. TD8 patches for that page will be loaded.")]
void OnPageNumChanged( object sender, EventArgs e )
{
IntEventArgs ie = e as IntEventArgs;
Debug.Assert(ie!=null,"TD8 OnPageNumChanged error: e is not an IntEventArgs");
}
[ProjectMidiActionAttribute("Patch#",128,"PatchNum","Selects the patch number for the current page. TD8 patches for that patch number will be loaded.")]
void OnPatchNumChanged( object sender, EventArgs e )
{
IntEventArgs ie = e as IntEventArgs;
Debug.Assert(ie!=null,"TD8 OnPatchNumChanged error: e is not an IntEventArgs");
}
#endregion
#region Properties
public bool DirtyFlag
{
get { return dirtyFlag; }
set { dirtyFlag = value; }
}
#endregion
#region TD8 Constructor
public TD8()
{
}
#endregion
#region ProjectMidiParent
// This will happen immediately after construction
public IProjectMidiParent ProjectMidiParent
{
set
{
projectMidiParent = value;
iprojectmidis = projectMidiParent.IProjectMidis;
//projectMidiParent.AllAssembliesLoadedEvent +=new ProjectMidiEventHandler(AllAssembliesLoadedHandler);
#region fill instGroupNames
instGroupNames[0] = vkickGroup;
instGroupNames[1] = kickGroup;
instGroupNames[2] = vsnareGroup;
instGroupNames[3] = snareGroup;
instGroupNames[4] = vtomGroup;
instGroupNames[5] = tomGroup;
instGroupNames[6] = hihatGroup;
instGroupNames[7] = crashGroup;
instGroupNames[8] = rideGroup;
instGroupNames[9] = percGroup;
instGroupNames[10] = specialGroup;
instGroupNames[11] = melodicGroup;
instGroupNames[12] = voiceGroup;
instGroupNames[13] = reverseGroup;
instGroupNames[14] = fixedhhGroup;
instGroupNames[15] = offGroup;
#endregion
// Fill the instrumentNames array
int x = 0;
foreach(string[] astr in instGroupNames)
{
foreach(string str in astr)
{
instrumentNames[x++] = str;
}
}
// Get our path to our individual TD-8 files
TD8Folder = Path.Combine(projectMidiParent.ProjectMidiPath,TD8FolderName);
TD8TemplateSysExFilePath = Path.Combine(TD8Folder,"Default.TD8");
if(!Directory.Exists(TD8Folder)) Directory.CreateDirectory( TD8Folder );
LoadAllKitsFromSysExFile(); // TODO: this may need to get moved to the DeviceDetected section(s)
}
}
#endregion
#region PerformStartProcessing
public void PerformStartProcessing( StartPhase phase )
{
switch(phase)
{
case StartPhase.AfterLoading:
break;
case StartPhase.AllAssembliesLoaded:
AllAssembliesLoaded();
break;
case StartPhase.StartConnecting:
break;
case StartPhase.FirstTimeEver:
CreateOurConnections();
break;
case StartPhase.AllAssembliesConnected:
break;
case StartPhase.Terminating:
break;
default:
Console.WriteLine("Unknown StartPhase");
break;
}
}
#endregion
#region CreateOurConnections
private void CreateOurConnections()
{
if(projectMidiParent==null) Console.WriteLine("TD8 ConnectOurConnections Error: projectMidiParent not set!");
else
{
// PDF Ink submenu
projectMidiParent.CreateAConnection("Menu", "PDFContextMenu",
"TD8", "Editor", "System", "-1",
"True", "False", "TD8 Editor");
// Icon Menu
projectMidiParent.CreateAConnection("Menu", "PMIconMenu",
"TD8", "Editor", "System", "-1",
"True", "False", "TD8 Editor");
// Midi In
projectMidiParent.CreateAConnection("Midi", "AnyIn",
"TD8", "MidiIn", "System", "-1",
"True", "False", null);
// Midi Out
projectMidiParent.CreateAConnection("TD8", "MidiOut",
"Midi", "AnyOut", "System", "-1",
"True", "False", null);
// Inc/Dec
projectMidiParent.CreateAConnection("TD8", "Inc/Dec",
"SongSet", "Song#", "System", "-1",
"True", "False", null);
}
}
#endregion
#region All Assemblies Loaded Handler
// Locate the ISongSet after all modules have been loaded
private void AllAssembliesLoaded()
{
Debug.Assert(iprojectmidis!=null,"TD8 AllAssembliesLoadedHandler error: iprojectmidis is null");
foreach(IProjectMidi iproj in iprojectmidis)
{
isongset = iproj as ISongSet;
if(isongset!=null) break;
}
}
#endregion
#region IProjectMidiHideShow Members
[ProjectMidiActionAttribute("Hide/Show",0,"","Hide or Show TD8 Editor window.")]
public void OnHideShow(object sender, EventArgs e) { HideShow(); }
public void HideShow()
{
if(frm == null)
{
frm = new TD8Edit();
frm.Td8 = this;
frm.Show();
//dirtyFlag = true; // Assume changes were made.
//Console.WriteLine("TD8: Saving changes");
//SavePatch();
//dirtyFlag = false;
}
else
{
frm.Close();
frm = null;
}
//this.Visible = !this.Visible;
}
#endregion
#region LoadAllKitsFromSysExFile
// Read all data from a SysEx dump file.
// This is used to provide 'template' kits
public void LoadAllKitsFromSysExFile()
{
Console.WriteLine("LoadAllBanksFromSysExFile()");
// Eventually, this should be loaded via SysEx from the TD-8 device itself.
// For now, this will be read from a file. Prompt for the file.
// RegistryKey key = projectMidiParent.ProjectMidiKey; //Registry.LocalMachine.CreateSubKey(RegistryPath);
// TD8Folder = (string)key.GetValue( TD8TemplateSysExFilePathKey );
// if(!File.Exists(TD8TemplateSysExFilePath))
// {
// OpenFileDialog dlg = new OpenFileDialog();
// dlg.Filter = "SysEx dump files (*.syx)|*.syx";
// dlg.Title = "Select TD-8 Patch File";
// if(dlg.ShowDialog()!=DialogResult.OK)
// {
// MessageBox.Show("Error loading TD8 SysEx file");
// return;
// }
// TD8TemplateSysExFilePath = dlg.FileName;
// key.SetValue( TD8TemplateSysExFilePathKey, TD8TemplateSysExFilePath );
// }
// Create an instance of StreamReader to read from a file.
// The using statement also closes the StreamReader.
if(!File.Exists(TD8TemplateSysExFilePath))
{
MessageBox.Show("TD8 file ("+TD8TemplateSysExFilePath+") not found.");
return;
}
using(FileStream fs = new FileStream(TD8TemplateSysExFilePath, FileMode.Open, FileAccess.Read))
{
numKits = (int)(fs.Length / 697);
if(numKits < 1)
{
Console.WriteLine("File is the wrong size ({0}). It must be at least 697 bytes.",fs.Length);
MessageBox.Show("File is the wrong size. It must be at least 697 bytes.");
numKits = 1;
kits = new TD8Kit[numKits];
return;
}
kits = new TD8Kit[numKits];
for( int drumKit = 0; drumKit < numKits; drumKit++)
{
kits[drumKit] = new TD8Kit();
LoadKitFromOpenSysExFile(kits[drumKit], drumKit, fs);
}
dirtyFlag = false;
}
}
#endregion
#region LoadKitFromOpenSysExFile
// Read data for a single kit from an open file.
public void LoadKitFromOpenSysExFile(TD8Kit kit, int kitid, FileStream fs)
{
TraceMessage("TD8: LoadKitFromOpenSysExFile");
//Console.WriteLine("LoadBankFromOpenSysExFile");
// Read 'Common' parameters (size 25 + 10 + 2)
int nBytes=NumSysExCommonBytes;
byte[] ByteArray=new byte[nBytes];
int nBytesRead=fs.Read(ByteArray, 0, nBytes);
if(nBytesRead != nBytes)
{
Console.WriteLine("Error: bytes read = {0} of expected {1}",nBytesRead,nBytes);
MessageBox.Show("Error 1 reading file.");
return;
}
LoadKitCommonFromBuffer(kit, kitid, ByteArray, nBytesRead);
// Read each pad's parameters (12)
for(int padNum = 0; padNum < TD8Kit.NumPads; padNum++)
{
// Read 'Pad' parameters (size 43 + 10 + 2)
nBytes=NumSysExPadBytes;
ByteArray=new byte[nBytes];
nBytesRead=fs.Read(ByteArray, 0, nBytes);
if(nBytesRead != nBytes)
{
Console.WriteLine("LoadKitFromOpenSysExFile Error: bytes read = {0} of expected {1}",nBytesRead,nBytes);
MessageBox.Show("Error 2 reading file.");
return;
}
LoadKitPadFromBuffer(kit, padNum, ByteArray, nBytesRead);
}
}
#endregion
#region LoadKitCommonFromBuffer
private void LoadKitCommonFromBuffer(TD8Kit kit, int kitid, byte[] data, int dsize)
{
//Console.WriteLine("LoadKitCommonFromBuffer");
// Read 'Common' parameters (size 25 + 10 + 2)
int nBytes=NumSysExCommonBytes;
if(nBytes < dsize)
{
Console.WriteLine("LoadKitCommonFromBuffer Error: dsize too small {0}",dsize);
MessageBox.Show("Error 3 reading file.");
return;
}
string name = "";
for(int i = SysExPrefixLen; i<SysExPrefixLen+8; i++) name += (char)data[i];
kit.Common.Name = name;
kit.Common.StudioType = (TD8Common.enumStudioType)data[SysExPrefixLen+8];
kit.Common.StudioLevel = data[SysExPrefixLen+9];
kit.Common.WallType = (TD8Common.enumWallType)data[SysExPrefixLen+10];
kit.Common.RoomSize = (TD8Common.enumRoomSize)data[SysExPrefixLen+11];
kit.Common.EQLowFreq = (TD8Common.enumEQLowFreq)data[SysExPrefixLen+12];
kit.Common.EQLowGain = data[SysExPrefixLen+13];
kit.Common.EQHighFreq = (TD8Common.enumEQHighFreq)data[SysExPrefixLen+14];
kit.Common.EQHighGain = data[SysExPrefixLen+15];
kit.Common.AmbienceOnOff = data[SysExPrefixLen+16]!=0;
kit.Common.EQOnOff = data[SysExPrefixLen+17]!=0;
kit.Common.BrushOnOff = data[SysExPrefixLen+18]!=0;
kit.Common.PedalHiHatVolume = data[SysExPrefixLen+19];
kit.Common.PedalBendRange = data[SysExPrefixLen+20];
kit.Common.MasterVolume = data[SysExPrefixLen+21];
kit.Common.AmbienceGroupKitSendLevel = data[SysExPrefixLen+22];
kit.Common.AmbienceGroupPercSendLevel = data[SysExPrefixLen+23];
kit.Common.AmbienceGroupPartSendLevel = data[SysExPrefixLen+24];
}
#endregion
#region LoadKitPadFromBuffer
private void LoadKitPadFromBuffer(TD8Kit kit, int padid, byte[] data, int dsize)
{
//Console.WriteLine("LoadKitPadFromBuffer");
// Read 'Pad' parameters (size 43 + 10 + 2)
if(dsize < NumSysExPadBytes)
{
Console.WriteLine("LoadKitPadFromBuffer Error: size {0} too small ({1})",dsize,NumSysExPadBytes);
MessageBox.Show("Error 4 reading file.");
return;
}
// Head
uint inst = (uint)(data[SysExPrefixLen]<<12); // nibbled
inst += (uint)(data[SysExPrefixLen+1]<<8);
inst += (uint)(data[SysExPrefixLen+2]<<4);
inst += data[SysExPrefixLen+3];
if(inst > 1024)
{
Console.WriteLine("LoadKitPadFromBuffer error: head inst > 1024 ({0})",inst);
inst = 0;
}
kit.Pads[padid].Pad[0].Instrument = inst; // 0-1024 nibbled
int pitch = data[SysExPrefixLen+4]<<12;
pitch += data[SysExPrefixLen+5]<<8;
pitch += data[SysExPrefixLen+6]<<4;
pitch += data[SysExPrefixLen+7];
if(pitch > 960)
{
Console.WriteLine("LoadKitPadFromBuffer error: head pitch > 960 ({0})",pitch);
pitch = 480;
}
kit.Pads[padid].Pad[0].Pitch = pitch; // 0-960 (-4800 - +4800 cent, 10 cent steps) nibbled
kit.Pads[padid].Pad[0].Decay = data[SysExPrefixLen+8];
uint ptrn = (uint)(data[SysExPrefixLen+9]<<12);
ptrn += (uint)(data[SysExPrefixLen+10]<<8);
ptrn += (uint)(data[SysExPrefixLen+11]<<4);
ptrn += data[SysExPrefixLen+12];
if(ptrn > 800)
{
Console.WriteLine("LoadKitPadFromBuffer error: head pattern > 800 ({0})",pitch);
pitch = 0;
}
kit.Pads[padid].Pad[0].PlayPatternNumber = ptrn; // 0-800 (0=off) nibbled
kit.Pads[padid].Pad[0].GateTime = data[SysExPrefixLen+13];
kit.Pads[padid].Pad[0].NoteNum = data[SysExPrefixLen+14];
kit.Pads[padid].Pad[0].PadPatternVelocity = data[SysExPrefixLen+15] != 0;
kit.Pads[padid].Pad[0].Level = data[SysExPrefixLen+16];
kit.Pads[padid].Pad[0].AmbienceSendLevel = data[SysExPrefixLen+17];
kit.Pads[padid].Pad[0].PitchCtrlAssign = data[SysExPrefixLen+18] != 0;
// Rim
inst = (uint)(data[SysExPrefixLen+19]<<12); // nibbled
inst += (uint)(data[SysExPrefixLen+20]<<8);
inst += (uint)(data[SysExPrefixLen+21]<<4);
inst += data[SysExPrefixLen+22];
if(inst > 1024)
{
Console.WriteLine("LoadKitPadFromBuffer error: rim inst > 1024 ({0})",inst);
inst = 0;
}
kit.Pads[padid].Pad[1].Instrument = inst; // 0-1024 (nibbled)
pitch = data[SysExPrefixLen+23]<<12;
pitch += data[SysExPrefixLen+24]<<8;
pitch += data[SysExPrefixLen+25]<<4;
pitch += data[SysExPrefixLen+26];
if(pitch > 960)
{
Console.WriteLine("LoadKitPadFromBuffer error: rim pitch > 960 ({0})",pitch);
pitch = 480;
}
kit.Pads[padid].Pad[1].Pitch = pitch; // 0-960 (-4800 - +4800 cent, 10 cent steps)
kit.Pads[padid].Pad[1].Decay = data[SysExPrefixLen+27];
ptrn = (uint)(data[SysExPrefixLen+28]<<12);
ptrn += (uint)(data[SysExPrefixLen+29]<<8);
ptrn += (uint)(data[SysExPrefixLen+30]<<4);
ptrn += (uint)(data[SysExPrefixLen+31]);
if(ptrn > 800)
{
Console.WriteLine("LoadKitPadFromBuffer error: rim pattern > 800 ({0})",pitch);
pitch = 0;
}
kit.Pads[padid].Pad[1].PlayPatternNumber = ptrn; // 0-800 (0=off)
kit.Pads[padid].Pad[1].GateTime = data[SysExPrefixLen+32];
kit.Pads[padid].Pad[1].NoteNum = data[SysExPrefixLen+33];
kit.Pads[padid].Pad[1].PadPatternVelocity = data[SysExPrefixLen+34] != 0;
kit.Pads[padid].Pad[1].Level = data[SysExPrefixLen+35];
kit.Pads[padid].Pad[1].AmbienceSendLevel = data[SysExPrefixLen+36];
kit.Pads[padid].Pad[1].PitchCtrlAssign = data[SysExPrefixLen+37] != 0;
kit.Pads[padid].Pan = data[SysExPrefixLen+38];
kit.Pads[padid].ShellDepth = (TD8Pad.enumShellDepth)(data[SysExPrefixLen+39]);
kit.Pads[padid].HeadType = (TD8Pad.enumHeadType)(data[SysExPrefixLen+40]);
kit.Pads[padid].Muffling = (TD8Pad.enumMuffling)(data[SysExPrefixLen+41]);
kit.Pads[padid].StrainerAdjustment = (TD8Pad.enumStrainerAdjustment)(data[SysExPrefixLen+42]);
}
#endregion
#region WriteAllKitsToSysExFile
// Write all data to a SysEx dump file.
public void WriteAllKitsToSysExFile()
{
//Console.WriteLine("WriteAllBanksToSysExFile()");
// Create an instance of StreamReader to write to a file.
// The using statement also closes the StreamReader.
using(FileStream fs = new FileStream(TD8TemplateSysExFilePath, FileMode.Create, FileAccess.Write))
{
if(numKits < 1)
{
Console.WriteLine("File is the wrong size ({0}). It must be at least 697 bytes.",fs.Length);
MessageBox.Show("WriteAllBanksToSysEx Error: numKits < 1.");
// Go ahead and correct the problem.
numKits = 1;
kits = new TD8Kit[numKits];
return;
}
for( int drumKit = 0; drumKit < numKits; drumKit++)
{
WriteKitToSysExFile(kits[drumKit], (byte)drumKit, fs);
}
}
}
#endregion
#region WriteKitToSysExFile
// Write all data to a SysEx dump file.
public void WriteKitToSysExFile(TD8Kit kit, byte kitid, FileStream fs)
{
//Console.WriteLine("WriteKitToSysExFile()");
// Write 'Common' parameters (size 25 + 10 + 2)
int nBytes=NumSysExCommonBytes;
byte[] data=new byte[nBytes];
WriteKitCommonToBuffer(kit, kitid, data, nBytes);
try
{
fs.Write(data, 0, nBytes);
}
catch( Exception e3 )
{
Console.WriteLine("Error writing common data: {0}",e3.Message);
MessageBox.Show("Error 1 writing file.");
return;
}
// Write each pad's parameters (12)
for(int padNum = 0; padNum < TD8Kit.NumPads; padNum++)
{
// Write 'Pad' parameters (size 43 + 10 + 2)
nBytes=NumSysExPadBytes;
data=new byte[nBytes];
WriteKitPadToBuffer(kit, kitid, padNum, data, NumSysExPadBytes);
try
{
fs.Write(data, 0, nBytes);
}
catch( Exception e3 )
{
Console.WriteLine("Error writing pad data: {0}",e3.Message);
MessageBox.Show("Error 2 writing file.");
return;
}
}
}
#endregion
#region WriteKitToBuffer
// Write all data to a data buffer.
public void WriteKitToBuffer(TD8Kit kit, byte kitid, byte[] data, int bufsize)
{
//Console.WriteLine("WriteKitToBuffer()");
if(bufsize < 697)
{
Console.WriteLine("WriteKitToBuffer Error: bufsize too small.");
return;
}
WriteKitCommonToBuffer(kit, kitid, data, bufsize);
// Write each pad's parameters (12)
for(int padNum = 0; padNum < TD8Kit.NumPads; padNum++)
{
int offset = NumSysExCommonBytes+(padNum*NumSysExPadBytes);
byte[] tdata = new byte[NumSysExPadBytes];
WriteKitPadToBuffer(kit, kitid, padNum, tdata, NumSysExPadBytes);
for(int i=0; i<NumSysExPadBytes; i++) data[offset+i]=tdata[i];
}
}
#endregion
#region WriteKitCommonToBuffer
// Write common section data to a data buffer.
public void WriteKitCommonToBuffer(TD8Kit kit, byte kitid, byte[] data, int bufsize)
{
//Console.WriteLine("WriteKitCommonToBuffer()");
if(bufsize < NumSysExCommonBytes)
{
Console.WriteLine("WriteKitCommonToBuffer Error: bufsize too small.");
return;
}
// Write 'Common' parameters (size 25 + 10 + 2)
data[0] = 0xf0;
data[1] = 0x41;
data[2] = DevNum; // dev;
data[3] = 0x00;
data[4] = 0x20;
data[5] = 0x12;
data[6] = 0x41; // addMSB;
data[7] = kitid; // add2;
data[8] = 0; // add3;
data[9] = 0; // addLSB;
for(int x=0; x<8; x++)
{
byte b = (byte)(kit.Common.Name[x]);
data[x+SysExPrefixLen] = b;
}
data[18] = (byte)kit.Common.StudioType;
data[19] = (byte)kit.Common.StudioLevel;
data[20] = (byte)kit.Common.WallType;
data[21] = (byte)kit.Common.RoomSize;
data[22] = (byte)kit.Common.EQLowFreq;
data[23] = (byte)kit.Common.EQLowGain;
data[24] = (byte)kit.Common.EQHighFreq;
data[25] = (byte)kit.Common.EQHighGain;
data[26] = (byte)(kit.Common.AmbienceOnOff ? 1 : 0);
data[27] = (byte)(kit.Common.EQOnOff ? 1 : 0);
data[28] = (byte)(kit.Common.BrushOnOff ? 1 : 0);
data[29] = (byte)kit.Common.PedalHiHatVolume;
data[30] = (byte)kit.Common.PedalBendRange;
data[31] = (byte)kit.Common.MasterVolume;
data[32] = (byte)kit.Common.AmbienceGroupKitSendLevel;
data[33] = (byte)kit.Common.AmbienceGroupPercSendLevel;
data[34] = (byte)kit.Common.AmbienceGroupPartSendLevel;
byte chksum = 0;
for(int x=6; x<35; x++)
{
chksum += data[x];
}
chksum = (byte)(chksum & 0x7f);
if(chksum > 0) chksum = (byte)(0x80 - (chksum & 0x7f));
data[35] = chksum;
data[36] = EOX;
}
#endregion
#region WriteKitPadToBuffer
// Write 1 pad's data to a data buffer.
public void WriteKitPadToBuffer(TD8Kit kit, byte kitid, int padNum, byte[] data, int bufsize)
{
//Console.WriteLine("WriteKitPadToBuffer()");
if(bufsize < NumSysExPadBytes)
{
Console.WriteLine("WriteKitPadToBuffer Error: bufsize too small.");
return;
}
// Write 'Pad' parameters (size 43 + 10 + 2)
data[0] = 0xf0;
data[1] = 0x41;
data[2] = DevNum; // dev;
data[3] = 0x00;
data[4] = 0x20;
data[5] = 0x12;
data[6] = 0x41; // addMSB;
data[7] = kitid; // add2;
data[8] = (byte)(1+padNum); // add3;
data[9] = 0; // addLSB;
// Head (use .Pad[0])
uint inst = kit.Pads[padNum].Pad[0].Instrument;
if(inst > 1023)
{
Console.WriteLine("Invalid inst # {0} pad {1}",inst,padNum);
inst = 0;
}
data[10] = (byte)((inst>>12) & 0x0f); // nibbled
data[11] = (byte)((inst>>8) & 0x0f);
data[12] = (byte)((inst>>4) & 0x0f);
data[13] = (byte)(inst & 0x0f);
uint pitch = (uint)(kit.Pads[padNum].Pad[0].Pitch); // 0-960 (-4800 - +4800 cent, 10 cent steps)
if(pitch > 960)
{
Console.WriteLine("Invalid pitch # {0} pad {1}",pitch,padNum);
pitch = 480;
}
data[14] = (byte)((pitch>>12) & 0x0f); // nibbled
data[15] = (byte)((pitch>>8) & 0x0f);
data[16] = (byte)((pitch>>4) & 0x0f);
data[17] = (byte)(pitch & 0x0f);
data[18] = (byte)kit.Pads[padNum].Pad[0].Decay;
uint ptrn = (uint)(kit.Pads[padNum].Pad[0].PlayPatternNumber); // 0-800 (0=off)
if(ptrn > 800)
{
Console.WriteLine("Invalid pattern # {0} pad {1}",ptrn,padNum);
ptrn = 0;
}
data[19] = (byte)((ptrn>>12) & 0x0f); // nibbled
data[20] = (byte)((ptrn>>8) & 0x0f);
data[21] = (byte)((ptrn>>4) & 0x0f);
data[22] = (byte)(ptrn & 0x0f);
data[23] = (byte)kit.Pads[padNum].Pad[0].GateTime;
data[24] = (byte)kit.Pads[padNum].Pad[0].NoteNum;
data[25] = (byte)(kit.Pads[padNum].Pad[0].PadPatternVelocity ? 1 : 0);
data[26] = (byte)kit.Pads[padNum].Pad[0].Level;
data[27] = (byte)kit.Pads[padNum].Pad[0].AmbienceSendLevel;
data[28] = (byte)(kit.Pads[padNum].Pad[0].PitchCtrlAssign ? 1 : 0);
// Rim (use .Pad[1])
inst = kit.Pads[padNum].Pad[1].Instrument;
if(inst > 1023)
{
Console.WriteLine("Invalid inst # {0} pad {1}",inst,padNum);
inst = 0;
}
data[29] = (byte)((inst>>12) & 0x0f); // nibbled
data[30] = (byte)((inst>>8) & 0x0f);
data[31] = (byte)((inst>>4) & 0x0f);
data[32] = (byte)(inst & 0x0f);
pitch = (uint)(kit.Pads[padNum].Pad[1].Pitch); // 0-960 (-4800 - +4800 cent, 10 cent steps)
if(pitch > 960)
{
Console.WriteLine("Invalid pitch # {0} pad {1}",pitch,padNum);
pitch = 480;
}
data[33] = (byte)((pitch>>12) & 0x0f); // nibbled
data[34] = (byte)((pitch>>8) & 0x0f);
data[35] = (byte)((pitch>>4) & 0x0f);
data[36] = (byte)(pitch & 0x0f);
data[37] = (byte)kit.Pads[padNum].Pad[1].Decay;
ptrn = (uint)(kit.Pads[padNum].Pad[1].PlayPatternNumber); // 0-800 (0=off)
if(ptrn > 800)
{
Console.WriteLine("Invalid pattern # {0} pad {1}",ptrn,padNum);
ptrn = 0;
}
data[38] = (byte)((ptrn>>12) & 0x0f); // nibbled
data[39] = (byte)((ptrn>>8) & 0x0f);
data[40] = (byte)((ptrn>>4) & 0x0f);
data[41] = (byte)(ptrn & 0x0f);
data[42] = (byte)kit.Pads[padNum].Pad[1].GateTime;
data[43] = (byte)kit.Pads[padNum].Pad[1].NoteNum;
data[44] = (byte)(kit.Pads[padNum].Pad[1].PadPatternVelocity ? 1 : 0);
data[45] = (byte)kit.Pads[padNum].Pad[1].Level;
data[46] = (byte)kit.Pads[padNum].Pad[1].AmbienceSendLevel;
data[47] = (byte)(kit.Pads[padNum].Pad[1].PitchCtrlAssign ? 1 : 0);
data[48] = (byte)kit.Pads[padNum].Pan;
data[49] = (byte)kit.Pads[padNum].ShellDepth;
data[50] = (byte)kit.Pads[padNum].HeadType;
data[51] = (byte)kit.Pads[padNum].Muffling;
data[52] = (byte)kit.Pads[padNum].StrainerAdjustment;
byte chksum = 0;
for(int x=6; x<53; x++)
{
chksum += data[x];
}
chksum = (byte)(chksum & 0x7f);
if(chksum > 0) chksum = (byte)(0x80 - (chksum & 0x7f));
data[53] = chksum;
data[54] = EOX;
}
#endregion
#region MidiInData
[ProjectMidiActionAttribute("MidiIn",1,"AnyMidiIn","Connected this to the desired MID-In port.")]
void OnMidiInData( object sender, EventArgs e )
{
ObjectEventArgs oe = e as ObjectEventArgs;
if(oe==null) return;
IMidiData mididata = oe.obj as IMidiData;
if(mididata==null) return;
//if(mididata.IsActiveSense || mididata.IsTimingClock) activeSense = true;
// Fire any actionss associated with this particular event
if(mididata.IsNoteOn)
{
switch( mididata.KeyNum )
{
// case BassDrumNoteNum:
// BassDrumDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case SnareDrumNoteNum:
// SnareDrumDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case SnareDrumRimNoteNum:
// SnareRimDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case HighHatNoteNum:
// HighHatDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case HighTomNoteNum:
// HighTomDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case MidTomNoteNum:
// MidTomDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case LowTomNoteNum:
// LowTomDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case FloorTomNoteNum:
// FloorTomDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case CrashCymbalNoteNum:
// CrashCymbalDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case SplashCymbalNoteNum:
// SplashCymbalDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
// case RideCymbalNoteNum:
// RideCymbalDevInput.Actions.FireActions( Name, mididata.Byte2 );
// break;
case CowbellNoteNum:
if(OnCowBellDevInput!=null) OnCowBellDevInput( this, new EventArgs() );
break;
}
}
else if(mididata.IsProgramChange)
{
if(OnIncDecDevInput!=null) OnIncDecDevInput( this, new IntEventArgs( mididata.ProgramNum) );
}
// Calculate tempo based on Snare, Bass and HH inputs
if( mididata.IsNoteOn )
{
switch(mididata.KeyNum)
{
case BassDrumNoteNum:
break;
case SnareDrumNoteNum:
break;
case HighHatNoteNum:
break;
}
}
}
#endregion
#region Select Patch Dialog
// SELECT PATCH DIALOG
[ProjectMidiActionAttribute("Editor",1,"","This causes the TD8 voice selection dialog to be displayed.")]
private void SelectPatchDialog( object sender, EventArgs e )
{
Console.WriteLine("SelectPatchDialog()");
if(frm == null)
{
frm = new TD8Edit();
frm.Td8 = this;
frm.Show();
//dirtyFlag = true; // Assume changes were made.
//Console.WriteLine("TD8: Saving changes");
//SavePatch();
//dirtyFlag = false;
}
}
#endregion
#region Set or Cache Patch
// SET OR CACHE PATCH
private bool SetOrCachePatch(string songFileName,int songListIndex,int pageNum,int patchNum)
{
Console.WriteLine("SetOrCachePatch: {0}, {1}, {2}, {3}",songFileName,songListIndex,pageNum,patchNum);
TraceMessage("TD8: SetOrCachePatch: "+songFileName+", page "+pageNum.ToString());
if(currentKitNum == songListIndex && dirtyFlag == true) // Do we need to save this kit?
{
Console.WriteLine("TD8: Saving previous patch");
SavePatch();
dirtyFlag = false;
}
TraceMessage("TD8: SongListIndex="+songListIndex.ToString());
if(kits[songListIndex].Common.Name == Path.GetFileNameWithoutExtension(songFileName))
{
Console.WriteLine("TD8: Patch {0} already cached: {1}.",songListIndex,songFileName);
TraceMessage("TD8: Patch already cached");
return true;
}
TraceMessage("TD8: Patch not already cached");
TraceMessage("TD8: folder = "+TD8Folder);
string patchFileName = Path.Combine(TD8Folder,Path.GetFileNameWithoutExtension(songFileName)+".TD8");
TraceMessage("Patch file name = "+patchFileName);
// Load the file if it exists and hasn't already been loaded
if( File.Exists( patchFileName ))
{
Console.WriteLine("TD8: Loading patch file");
TraceMessage("TD8: Loading patch file");
using(FileStream fs = new FileStream(patchFileName, FileMode.Open, FileAccess.Read))
{
if(fs.Length < 697)
{
Console.WriteLine("File is the wrong size ({0}). It must be at least 697 bytes.",fs.Length);
MessageBox.Show("File is the wrong size. It must be at least 697 bytes.");
return false;
}
LoadKitFromOpenSysExFile(kits[songListIndex], songListIndex, fs);
}
}
else
{
TraceMessage("File not found. Copying default kit.");
Console.WriteLine("TD8: Copying default kit");
// Otherwise, copy the default template and give it the song name
CopyKit( kits[songListIndex], kits[DefaultKitNum] );
kits[songListIndex].Common.Name = Path.GetFileNameWithoutExtension(songFileName);
}
//Console.WriteLine("SetPatch writing program change {0}",currentKitNum);
//int rc = outputPort.Write((byte)(MidiStatus.ProgramChange+DevMidiChan),(byte)currentKitNum,0);
// Now write the patch to the TD-8
TraceMessage("Sending kit");
Console.WriteLine("TD8: Sending kit {0} to TD8",songListIndex);
SendKitToTD8( songListIndex );
Thread.Sleep(40);
return true;
}
#endregion
#region Save Patch
// SAVE PATCH
internal int SavePatch()
{
Console.WriteLine("SavePatch()");
int rc = 0;
if(dirtyFlag == true) // Do we need to save this kit?
{
// Is this the default filename?
if(currentFileName == Path.Combine(TD8Folder,"Default.TD8"))
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "SysEx dump files (*.td8)|*.td8";
dlg.Title = "Select TD-8 Patch File";
dlg.InitialDirectory = TD8Folder;
if(dlg.ShowDialog()==DialogResult.OK)
{
currentFileName = dlg.FileName;
}
}
try
{
// Save the current kit (unless it is default?)
using(FileStream fs = new FileStream(currentFileName, FileMode.Create, FileAccess.Write))
{
WriteKitToSysExFile(kits[currentKitNum], (byte)currentKitNum, fs);
}
}
catch( Exception e )
{
Console.WriteLine("Error: {0}",e.Message);
rc = 4;
}
dirtyFlag = false;
}
return rc;
}
#endregion
#region Send Kit to TD8
// SEND KIT TO TD8
public int SendKitCommonToTD8(int patchID)
{
int rc = 0;
//Console.WriteLine("SendKitCommonToTD8()");
// Write 'Common' parameters (size 25 + 10 + 2)
int nBytes=NumSysExCommonBytes;
byte[] data=new byte[nBytes];
WriteKitCommonToBuffer(kits[patchID], (byte)patchID, data, nBytes);
SysExMessage message = new SysExMessage(SysExType.Start, data);
MidiOut(message,0);
Thread.Sleep(15);
return rc;
}
public int SendKitPadToTD8(int patchID, int padid)
{
int rc = 0;
//Console.WriteLine("SendKitPadToTD8()");
int nBytes=NumSysExPadBytes;
byte[] data=new byte[nBytes];
WriteKitPadToBuffer(kits[patchID], (byte)patchID, padid, data, nBytes);
SysExMessage message = new SysExMessage(SysExType.Start, data);
MidiOut(message,0);
Thread.Sleep(15);
return rc;
}
public int SendKitToTD8(int patchID)
{
int rc = 0;
SendKitCommonToTD8(patchID);
// Write out all 12 pads
for(int p=0; p<12; p++)
{
SendKitPadToTD8(patchID, p);
}
return rc;
}
// SEND a Byte to the TD8
public int SendByteParameterToTD8(byte b, byte a1, byte a2, byte a3, byte a4)
{
//Console.WriteLine("SendByteParameterToTD8 {0}, {1}",b,(a1<<12)+(a2<<8)+(a3<<4)+a4);
int rc = 0;
byte[] data = new byte[13];
data[0] = 0xf0;
data[1] = 0x41;
data[2] = DevNum; // dev;
data[3] = 0x00;
data[4] = 0x20;
data[5] = 0x12;
data[6] = a1; // addMSB;
data[7] = a2; // add2;
data[8] = a3; // add3;
data[9] = a4; // addLSB;
data[10] = b;
byte chksum = 0;
for(int x=6; x<11; x++)
{
chksum += data[x];
}
chksum = (byte)(chksum & 0x7f);
if(chksum > 0) chksum = (byte)(0x80 - (chksum & 0x7f));
data[11] = chksum;
data[12] = EOX;
SysExMessage message = new SysExMessage(SysExType.Start, data);
MidiOut(message,0);
Thread.Sleep(15);
return rc;
}
public int SendNibbledParameterToTD8(uint parm, byte a1, byte a2, byte a3, byte a4)
{
int rc = 0;
//Console.WriteLine("SendNibbledParameterToTD8 {0}, {1}",b,(a1<<12)+(a2<<8)+(a3<<4)+a4);
byte[] data = new byte[16];
data[0] = 0xf0;
data[1] = 0x41;
data[2] = DevNum; // dev;
data[3] = 0x00;
data[4] = 0x20;
data[5] = 0x12;
data[6] = a1; // addMSB;
data[7] = a2; // add2;
data[8] = a3; // add3;
data[9] = a4; // addLSB;
data[10] = (byte)((parm>>12) & 0x0f); // nibbled
data[11] = (byte)((parm>>8) & 0x0f);
data[12] = (byte)((parm>>4) & 0x0f);
data[13] = (byte)(parm & 0x0f);
byte chksum = 0;
for(int x=6; x<14; x++)
{
chksum += data[x];
}
chksum = (byte)(chksum & 0x7f);
if(chksum > 0) chksum = (byte)(0x80 - (chksum & 0x7f));
data[14] = chksum;
data[15] = EOX;
SysExMessage message = new SysExMessage(SysExType.Start, data);
MidiOut(message,0);
Thread.Sleep(15);
return rc;
}
#endregion
#region Copy Kit
// Copy every kit member except name
public void CopyKit(TD8Kit dest, TD8Kit src)
{
TraceMessage("CopyKit");
Console.WriteLine("CopyKit()");
try
{
//dest.Common.Name = src.Common.Name;
dest.Common.StudioType = src.Common.StudioType;
dest.Common.StudioLevel = src.Common.StudioLevel;
dest.Common.WallType = src.Common.WallType;
dest.Common.RoomSize = src.Common.RoomSize;
dest.Common.EQLowFreq = src.Common.EQLowFreq;
dest.Common.EQLowGain = src.Common.EQLowGain;
dest.Common.EQHighFreq = src.Common.EQHighFreq;
dest.Common.EQHighGain = src.Common.EQHighGain;
dest.Common.AmbienceOnOff = src.Common.AmbienceOnOff;
dest.Common.EQOnOff = src.Common.EQOnOff;
dest.Common.BrushOnOff = src.Common.BrushOnOff;
dest.Common.PedalHiHatVolume = src.Common.PedalHiHatVolume;
dest.Common.PedalBendRange = src.Common.PedalBendRange;
dest.Common.MasterVolume = src.Common.MasterVolume;
dest.Common.AmbienceGroupKitSendLevel = src.Common.AmbienceGroupKitSendLevel;
dest.Common.AmbienceGroupPercSendLevel = src.Common.AmbienceGroupPercSendLevel;
dest.Common.AmbienceGroupPartSendLevel = src.Common.AmbienceGroupPartSendLevel;
// Write each pad's parameters (12)
for(int padNum = 0; padNum < TD8Kit.NumPads; padNum++)
{
dest.Pads[padNum].HeadType = src.Pads[padNum].HeadType;
dest.Pads[padNum].Muffling = src.Pads[padNum].Muffling;
dest.Pads[padNum].Pan = src.Pads[padNum].Pan;
dest.Pads[padNum].ShellDepth = src.Pads[padNum].ShellDepth;
dest.Pads[padNum].StrainerAdjustment = src.Pads[padNum].StrainerAdjustment;
for(int x=0; x<2; x++)
{
dest.Pads[padNum].Pad[x].AmbienceSendLevel = src.Pads[padNum].Pad[x].AmbienceSendLevel;
dest.Pads[padNum].Pad[x].Decay = src.Pads[padNum].Pad[x].Decay;
dest.Pads[padNum].Pad[x].GateTime = src.Pads[padNum].Pad[x].GateTime;
dest.Pads[padNum].Pad[x].Instrument = src.Pads[padNum].Pad[x].Instrument;
dest.Pads[padNum].Pad[x].Level = src.Pads[padNum].Pad[x].Level;
dest.Pads[padNum].Pad[x].NoteNum = src.Pads[padNum].Pad[x].NoteNum;
dest.Pads[padNum].Pad[x].PadPatternVelocity = src.Pads[padNum].Pad[x].PadPatternVelocity;
dest.Pads[padNum].Pad[x].Pitch = src.Pads[padNum].Pad[x].Pitch;
dest.Pads[padNum].Pad[x].PitchCtrlAssign = src.Pads[padNum].Pad[x].PitchCtrlAssign;
dest.Pads[padNum].Pad[x].PlayPatternNumber = src.Pads[padNum].Pad[x].PlayPatternNumber;
}
}
}
catch(Exception e)
{
TraceMessage("Error in CopyKit: "+e.Message);
Console.WriteLine("TD8 CopyKit error: {0}",e.Message);
}
}
#endregion
#region OnMidiOut Event
// This is our out-going MIDI Event. We use it to pass messages
// to the MIDI port, or any other midi listeners.
[ProjectMidiEventAttribute("MidiOut",1,"AnyMidiOut",ConnectionType.Normal,"Connect this to the MIDI Port that the TD8 is attached to.")]
public event ProjectMidiEventHandler OnMidiOut;
public void MidiOut( MidiData mdata, uint timestamp )
{
try
{
// Pass the string msg in a StringEventArgs (derived from EventArgs)
ObjectEventArgs e = new ObjectEventArgs( mdata );
// Fire the event (if connected).
if(OnMidiOut!=null) OnMidiOut( this, e );
// Display a copy also in our output window during debugging.
Console.WriteLine("TD8 MidiOut: {0}",mdata.ToString());
}
catch(Exception err)
{
Console.WriteLine("TD8 MidiOut error: {0}",err.Message);
}
}
public void MidiOut( SysExMessage message, uint timestamp )
{
try
{
// Pass the string msg in a StringEventArgs (derived from EventArgs)
ObjectEventArgs e = new ObjectEventArgs( message );
// Fire the event (if connected).
if(OnMidiOut!=null) OnMidiOut( this, e );
// Display a copy also in our output window during debugging.
Console.WriteLine("TD8 MidiOut: SysEx");
}
catch(Exception err)
{
Console.WriteLine("TD8 MidiOut SysEx error: {0}",err.Message);
}
}
#endregion
#region Trace
[ProjectMidiEventAttribute("Trace",1,"TraceMessage",ConnectionType.Trace,"Sends TD8 diagnostic trace messages.")]
public event ProjectMidiEventHandler OnTraceMessage;
public void TraceMessage( string msg )
{
try
{
// Pass the string msg in a StringEventArgs (derived from EventArgs)
StringEventArgs e = new StringEventArgs( msg );
// Fire the event (if connected).
if(OnTraceMessage!=null) OnTraceMessage( this, e );
// Display a copy also in our output window during debugging.
Console.WriteLine("SampleAssembly TraceMessage: {0}",msg);
}
catch(Exception err)
{
Console.WriteLine("SampleAssembly TraceMessage error: {0}",err.Message);
}
}
#endregion
}
}