private static string DescribeKeySignature(byte[] bytes) { int n = MidiMetaEvent.GetDataLength(MidiMetaEvent.KeySignatureType); if (bytes.Length < n) { return(null); } MidiKeySignature k = MidiMetaEvent.DataToKeySignature(bytes); return((k == MidiKeySignature.NA) ? null : k.ToString().Replace("Flat", "b").Replace("Sharp", "#").Replace("Major", " major").Replace("Minor", " minor")); }
/// <summary>Gets the key signature in effect at a given (total) time.</summary> /// <param name="time">The total time (in ticks) at which to get the effective key signature.</param> /// <returns>The key signature at the specified time.</returns> public MidiKeySignature GetKeySignature(int time) { MidiKeySignature keySignature = MidiKeySignature.NA; foreach (KeyValuePair <int, MidiKeySignature> pair in this.KeySignatureMap) { if (pair.Key > time) { break; } keySignature = pair.Value; } return(keySignature); }
/// <summary>Adds an entry to the key signature map, or updates the entry if it already exists.</summary> /// <param name="metaEvent">A MidiMetaEvent object representing a key signature.</param> public void SetKeySignature(MidiMetaEvent metaEvent) { if (metaEvent.TotalTime < 0) { return; } MidiKeySignature keySignature = MidiMetaEvent.DataToKeySignature(metaEvent.Data); if (keySignature == MidiKeySignature.NA) { return; } this.KeySignatureMap[metaEvent.TotalTime] = keySignature; }
/// <summary> /// Changes the total (cumulative) time of each MTrk event in a track chunk, starting /// at the specified index in this file's list, by the specified number of ticks. /// </summary> /// <param name="index">The index of the event in this file's list at which to start the change.</param> /// <param name="delta">The number of ticks by which to change the total time of each event.</param> public void AdjustTotalTimes(int index, int delta) { if (delta == 0) { return; } /* Starting at the specified index, change the total time of each event in the list (until end- * of-list or a non-event is encountered, presumably indicating the end of the track/chunk), * and collect a list of key signature map "keys" (i.e., total times) affected by the change. */ List <int> keys = new List <int>(); for (int i = index; i < this.ItemCount; ++i) { MidiEvent mtrkEvent = this.Items[i] as MidiEvent; if (mtrkEvent == null) { break; } mtrkEvent.TotalTime += delta; /* If this is a meta-event representing a key signature, add its former * total time to the list of keys (total times) affected by this change. */ MidiMetaEvent metaEvent = MidiFile.ItemToKeySignatureEvent(mtrkEvent); if (metaEvent != null) { keys.Add(metaEvent.TotalTime - delta); } } /* Since our key signature map is keyed by total time, it must be adjusted correspondingly. * Replace each affected entry with a new one having the updated "key" (total time). */ if (delta > 0) { keys.Reverse(); } foreach (int key in keys) { MidiKeySignature keySignature = this.KeySignatureMap[key]; this.KeySignatureMap.Remove(key); this.KeySignatureMap[key + delta] = keySignature; } }
private static string DescribeInstrument(int data, int channel, MidiKeySignature keySignature) { return(MidiChannelEvent.InstrumentMap[data]); }
private static string DescribeController(int data, int channel, MidiKeySignature keySignature) { return(MidiChannelEvent.ControllerMap[data]); }
/// <summary>Converts a numeric value to a string representation of its assigned note(s).</summary> /// <param name="n">Numeric value assigned to note (middle C has a reference value of 60).</param> /// <returns>String representation of note(s) to which numeric value is assigned.</returns> private static string DescribeNote(int n, int channel, MidiKeySignature keySignature) { /* If appropriate, notate as percussion. */ if (channel == 9 && MidiChannelEvent.PercussionMap.ContainsKey(n)) { return(MidiChannelEvent.PercussionMap[n]); } /* Otherwise, notate as pitch. */ string s = null; int i = (n / 12) - 1; /* If there is no key signature, assume C major. */ MidiKeySignature k = (keySignature == MidiKeySignature.NA) ? MidiKeySignature.CMajor : keySignature; /* Convert the numeric value based on key signature (see MidiKeySignature notation chart). */ switch (n % 12) { case 0: if (k > MidiKeySignature.EMajor && k < MidiKeySignature.CFlatMajor) { s = "B#"; --i; } else { s = "C"; } break; case 1: s = (k > MidiKeySignature.FMajor || k < MidiKeySignature.CFlatMajor) ? "C#" : "Db"; break; case 2: s = "D"; break; case 3: s = (k > MidiKeySignature.GMajor && k < MidiKeySignature.CFlatMajor) ? "D#" : "Eb"; break; case 4: s = (k == MidiKeySignature.CFlatMajor || k == MidiKeySignature.AFlatMinor) ? "Fb" : "E"; break; case 5: s = (k > MidiKeySignature.AMajor && k < MidiKeySignature.CFlatMajor) ? "E#" : "F"; break; case 6: s = (k > MidiKeySignature.BFlatMinor || k < MidiKeySignature.CFlatMajor) ? "F#" : "Gb"; break; case 7: s = "G"; break; case 8: s = (k > MidiKeySignature.CMajor && k < MidiKeySignature.CFlatMajor) ? "G#" : "Ab"; break; case 9: s = "A"; break; case 10: s = (k > MidiKeySignature.DMajor && k < MidiKeySignature.CFlatMajor) ? "A#" : "Bb"; break; case 11: if (k >= MidiKeySignature.CFlatMajor && k < MidiKeySignature.DFlatMajor) { s = "Cb"; ++i; } else { s = "B"; } break; default: return(string.Empty); } return(s + " " + ((i < 0) ? "-" : (i > 9) ? "+" : i.ToString())); }
/// <summary>Returns a comment for the first data byte of a channel message/event.</summary> /// <param name="messageType">Identifies the type of channel message (high nibble of status byte).</param> /// <param name="data">The first data byte of the event.</param> /// <param name="channel">One of the sixteen logical MIDI channels on which the event is transmitted.</param> /// <param name="keySignature">A MidiKeySignature value that applies to the event.</param> /// <returns>A comment for the data byte.</returns> public static string GetData1Comment(MidiMessageType messageType, int data, int channel, MidiKeySignature keySignature) { string s = (MidiChannelEvent.TypeMap[messageType].DescribeData1 == null) ? null : MidiChannelEvent.TypeMap[messageType].DescribeData1(data, channel, keySignature); return(MidiChannelEvent.BuildDataComment(MidiChannelEvent.TypeMap[messageType].Data1Name, data, s)); }