public void Write_DeleteDefaultTimeSignature() { var nonDefaultTimeSignatureEvent = new TimeSignatureEvent(2, 16); var midiFile = new MidiFile( new TrackChunk( new NoteOnEvent((SevenBitNumber)100, (SevenBitNumber)50), new NoteOffEvent((SevenBitNumber)100, (SevenBitNumber)50), new UnknownMetaEvent(254), new TimeSignatureEvent(), nonDefaultTimeSignatureEvent)); Write( midiFile, settings => settings.DeleteDefaultTimeSignature = true, (fileInfo1, fileInfo2) => { var originalMidiFile = MidiFile.Read(fileInfo1.FullName); Assert.AreEqual( 2, originalMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <TimeSignatureEvent>().Count(), "Invalid count of Time Signature events in original file."); var newMidiFile = MidiFile.Read(fileInfo2.FullName); var timeSignatureEvents = newMidiFile.GetTrackChunks().SelectMany(c => c.Events).OfType <TimeSignatureEvent>().ToArray(); Assert.AreEqual( 1, timeSignatureEvents.Length, "Invalid count of Time Signature events in new file."); MidiAsserts.AreEventsEqual(timeSignatureEvents[0], nonDefaultTimeSignatureEvent, false, "Invalid Time Signature event."); }); }
public MidiMBT(MidiFile mf) { timeSignature = mf.Events[0].OfType <TimeSignatureEvent>().FirstOrDefault(); BeatsPerBar = timeSignature == null ? 4 : timeSignature.Numerator; TicksPerBar = timeSignature == null ? mf.DeltaTicksPerQuarterNote * 4 : (timeSignature.Numerator * mf.DeltaTicksPerQuarterNote * 4) / (1 << timeSignature.Denominator); TicksPerBeat = TicksPerBar / BeatsPerBar; }
// Token: 0x06002A63 RID: 10851 RVA: 0x001380BC File Offset: 0x001362BC private static void smethod_5(EventsCollection eventsCollection_0, Song gclass27_0) { if (!GClass30.bool_0) { foreach (MidiEvent midiEvent in eventsCollection_0) { TimeSignatureEvent timeSignatureEvent = midiEvent as TimeSignatureEvent; if (timeSignatureEvent != null) { long absoluteTime = midiEvent.AbsoluteTime; gclass27_0.method_39(new GClass25((uint)absoluteTime, (uint)timeSignatureEvent.Numerator, (uint)timeSignatureEvent.Denominator), false); } else { SetTempoEvent setTempoEvent = midiEvent as SetTempoEvent; if (setTempoEvent != null) { long absoluteTime2 = midiEvent.AbsoluteTime; gclass27_0.method_39(new GClass24((uint)absoluteTime2, (uint)(60000000.0 / (double)setTempoEvent.MicrosecondsPerQuarterNote * 1000.0)), false); } else { TextEvent textEvent = midiEvent as TextEvent; if (textEvent != null) { gclass27_0.string_0 = textEvent.Text; } } } } gclass27_0.method_15(); } }
/// <summary> /// Get Minecraft Tick When a Midi Event Starts /// </summary> /// <param name="eventTime">Current Tick</param> /// <param name="ticksPerQuarterNote">TP QuarterNote</param> /// <param name="timeSignature">timeSignate</param> /// <param name="bpm">Current BPM</param> /// <param name="bpm_key_t">Current Tick of BPM Event</param> /// <param name="bpm_key_mt">Current Minecraft Tick of BPM Event</param> /// <returns>Tick Start</returns> #region Functional private long MinecraftTickStart(long eventTime, int ticksPerQuarterNote, TimeSignatureEvent timeSignature, double bpm, long bpm_key_t, long bpm_key_mt) { int beatsPerBar = timeSignature == null ? 4 : timeSignature.Numerator; int ticksPerBar = timeSignature == null ? ticksPerQuarterNote * 4 : (timeSignature.Numerator * ticksPerQuarterNote * 4) / (1 << timeSignature.Denominator); int ticksPerBeat = ticksPerBar / beatsPerBar; return((long)(((double)(eventTime - bpm_key_t)) * 1200 / ((double)(ticksPerBeat * bpm)) + bpm_key_mt)); //Tick per Minute }
/// <summary> /// Get Duration of a Midi Event as Minecraft Tick /// </summary> /// <param name="eventTime">Current Tick</param> /// <param name="ticksPerQuarterNote">TP QuarterNote</param> /// <param name="timeSignature">timeSignate</param> /// <param name="bpm">Current BPM</param> /// <returns>Tick Duration</returns> private long MinecraftTickDuration(long eventTime, int ticksPerQuarterNote, TimeSignatureEvent timeSignature, int bpm) { int beatsPerBar = timeSignature == null ? 4 : timeSignature.Numerator; int ticksPerBar = timeSignature == null ? ticksPerQuarterNote * 4 : (timeSignature.Numerator * ticksPerQuarterNote * 4) / (1 << timeSignature.Denominator); int ticksPerBeat = ticksPerBar / beatsPerBar; return((long)(((double)eventTime) * 1200 / ((double)(ticksPerBeat * bpm)))); }
private long GetBeat(long eventTime, int ticksPerQuarterNote, TimeSignatureEvent timeSignature) { int beatsPerBar = timeSignature == null ? 4 : timeSignature.Numerator; int ticksPerBar = timeSignature == null ? ticksPerQuarterNote * 4 : (timeSignature.Numerator * ticksPerQuarterNote * 4) / (1 << timeSignature.Denominator); int ticksPerBeat = ticksPerBar / beatsPerBar; long beat = 1 + ((eventTime % ticksPerBar) / ticksPerBeat); return(beat); }
private static string ToMBT(long eventTime, int ticksPerQuarterNote, TimeSignatureEvent timeSignature) { int beatsPerBar = timeSignature == null ? 4 : timeSignature.Numerator; int ticksPerBar = timeSignature == null ? ticksPerQuarterNote * 4 : (timeSignature.Numerator * ticksPerQuarterNote * 4) / (1 << timeSignature.Denominator); int ticksPerBeat = ticksPerBar / beatsPerBar; long bar = 1 + (eventTime / ticksPerBar); long beat = 1 + ((eventTime % ticksPerBar) / ticksPerBeat); long tick = eventTime % ticksPerBeat; return(String.Format("{0}:{1}:{2}", bar, beat, tick)); }
private long[] GetMBT(long eventTime, int ticksPerQuarterNote, TimeSignatureEvent timeSignature) { int beatsPerBar = timeSignature == null ? 4 : timeSignature.Numerator; int ticksPerBar = timeSignature == null ? ticksPerQuarterNote * 4 : (timeSignature.Numerator * ticksPerQuarterNote * 4) / (1 << timeSignature.Denominator); int ticksPerBeat = ticksPerBar / beatsPerBar; long bar = 1 + (eventTime / ticksPerBar); long beat = 1 + ((eventTime % ticksPerBar) / ticksPerBeat); long tick = eventTime % ticksPerBeat; //bar, beat, tick long[] mbt = new[] { bar, beat, tick }; return(mbt); }
private void ReadMidiFile(MidiFile midiFile, List <MidiNote> midiNotes) { if (midiFile.Tracks > 1) { Debug.LogWarning("Warning! Midi file has more than one track. Taking first track"); } int totalMidiEvents = midiFile.Events[0].Count; for (int i = 0; i < totalMidiEvents; i++) { MidiEvent midiEvent = midiFile.Events[0][i]; if (timeSignature is null) { try { timeSignature = (TimeSignatureEvent)midiEvent; } catch (InvalidCastException e) when(e.Data != null) { } } if (!MidiEvent.IsNoteOff(midiEvent)) { // Get the final tick of the song if (i == totalMidiEvents - 1) { int eventTime = (int)midiEvent.AbsoluteTime; if (eventTime > finalTick) { finalTick = eventTime; } } // Ensure that the midievent is a note, and not metadata if (midiEvent.CommandCode.ToString() == "NoteOn") { // Note length is retrieved from the next midiEvent's deltaTime float noteLength = 0; // Not at the end yet if (i < totalMidiEvents) { MidiEvent nextMidievent = midiFile.Events[0][i + 1]; noteLength = ((float)nextMidievent.DeltaTime / ticksperQuarterNote); } Debug.Log(noteLength); MidiNote note = GenerateMidiNote(midiEvent.AbsoluteTime, noteLength); midiNotes.Add(note); } } } }
private void AnalyzeTimeSignature(MetaEvent meta) { TimeSignatureEvent timesig = (TimeSignatureEvent)meta; // Numerator: counts the number of beats in a measure. // For example a numerator of 4 means that each bar contains four beats. MPTK_TimeSigNumerator = timesig.Numerator; // Denominator: number of quarter notes in a beat.0=ronde, 1=blanche, 2=quarter, 3=eighth, etc. MPTK_TimeSigDenominator = timesig.Denominator; MPTK_NumberBeatsMeasure = timesig.Numerator; MPTK_NumberQuarterBeat = System.Convert.ToInt32(System.Math.Pow(2, timesig.Denominator)); MPTK_TicksInMetronomeClick = timesig.TicksInMetronomeClick; MPTK_No32ndNotesInQuarterNote = timesig.No32ndNotesInQuarterNote; }
/// <summary> /// Find the number of beats per measure /// (for now assume just one TimeSignature per MIDI track) /// </summary> private int FindBeatsPerMeasure(IEnumerable <MidiEvent> midiEvents) { int beatsPerMeasure = 4; foreach (MidiEvent midiEvent in midiEvents) { TimeSignatureEvent tse = midiEvent as TimeSignatureEvent; if (tse != null) { beatsPerMeasure = tse.Numerator; } } return(beatsPerMeasure); }
public void TimeSignatureEvent() { var ticks = 19864u; byte nn = 0; byte dd = 0; byte cc = 0; byte bb = 0; var x = new TimeSignatureEvent(ticks, nn, dd, cc, bb); var y = ReDeserialize(x); Assert.That(x.Ticks == y.Ticks); Assert.That(x.numerator == y.numerator); Assert.That(x.denominator == y.denominator); Assert.That(x.midiClocksPerClick == y.midiClocksPerClick); Assert.That(x.numberOfNotated32nds == y.numberOfNotated32nds); }
private void AnalyzeTimeSignature(MetaEvent meta, TrackMidiEvent trackEvent = null) { TimeSignatureEvent timesig = (TimeSignatureEvent)meta; // Numerator: counts the number of beats in a measure. // For example a numerator of 4 means that each bar contains four beats. MPTK_TimeSigNumerator = timesig.Numerator; // Denominator: number of quarter notes in a beat.0=ronde, 1=blanche, 2=quarter, 3=eighth, etc. MPTK_TimeSigDenominator = timesig.Denominator; MPTK_NumberBeatsMeasure = timesig.Numerator; MPTK_NumberQuarterBeat = System.Convert.ToInt32(Mathf.Pow(2f, timesig.Denominator)); MPTK_TicksInMetronomeClick = timesig.TicksInMetronomeClick; MPTK_No32ndNotesInQuarterNote = timesig.No32ndNotesInQuarterNote; if (LogEvents && trackEvent != null) { Debug.Log(BuildInfoTrack(trackEvent) + string.Format("Meta {0,-15} Numerator:{1} Denominator:{2}", meta.MetaEventType, timesig.Numerator, timesig.Denominator)); } }
/// <summary> Constructs an IMidiFile instance based on a MIDI file stream.</summary> /// <param name="stream"> stream of the midi file content. </param> /// <param name="disposeStream"> Set true if stream is to be closed by the constructor once it's done reading the file. </param> internal DryWetMidiAdapter(Stream stream, bool disposeStream = false) { // initialization Stream = stream; stream.Position = 0; _midiContent = MidiFile.Read(stream); _tempoMap = _midiContent.GetTempoMap(); IList <TrackChunk> trackChunks = _midiContent.GetTrackChunks().ToList(); _metadataTrack = trackChunks.First(); _metaEvents = _metadataTrack.Events.ToList(); // set midi title property Title = (((from e in _metaEvents where e.EventType == MidiEventType.SequenceTrackName select e).First()) as BaseTextEvent)?.Text ?? "Undefined"; // set key signature property TimeSignatureEvent timeSignatureEvent = (from e in _metaEvents where e.EventType == MidiEventType.TimeSignature select e)?.First() as TimeSignatureEvent; KeySignature = MusicTheoryFactory.CreateDuration(timeSignatureEvent.Numerator, timeSignatureEvent.Denominator, false); // set number of bars property BarBeatFractionTimeSpan duration = _midiContent.GetDuration <BarBeatFractionTimeSpan>(); NumberOfBars = (int)duration.Bars + (int)Math.Ceiling(duration.Beats / timeSignatureEvent.Numerator); // set BPM property BeatsPerMinute = (byte)(_midiContent.GetTempoMap()?.Tempo.AtTime(0).BeatsPerMinute); // set MIDI pitch range IEnumerable <DWMidiI.Note> notes = _midiContent.GetNotes(); LowestPitch = (NotePitch)(byte)(notes.Min(note => note.NoteNumber)); HighestPitch = (NotePitch)(byte)(notes.Max(note => note.NoteNumber)); // dispose stream if requested if (disposeStream) { stream.Dispose(); } }
// BAD. Should have one for numerator, one for denominator private TimeSignatureEvent getTimeSignature() { // should there be a default state? for (int track = 0; track < m_data.Tracks; track++) { foreach (MidiEvent e in m_data[track]) { if (e.CommandCode == MidiCommandCode.MetaEvent) { if (e is TimeSignatureEvent) { TimeSignatureEvent n = (TimeSignatureEvent)e; m_timeSig = n; break; // not allowing time signature changes } } } } return(m_timeSig); }
private List <TimeSignatureChange> FindTimeSignatures(List <MidiEvent> midiEvents) { long currentTime = -1; List <TimeSignatureChange> timeSignatureEvents = new List <TimeSignatureChange>(); foreach (MidiEvent midiEvent in midiEvents) { TimeSignatureEvent tse = midiEvent as TimeSignatureEvent; if (tse != null) { if (tse.AbsoluteTime <= currentTime) { throw new ArgumentException("Unsorted Time Signatures found"); } // TODO: work out how to get the start measure int startMeasure = 1; timeSignatureEvents.Add(new TimeSignatureChange(tse.AbsoluteTime, tse.Numerator, startMeasure)); currentTime = tse.AbsoluteTime; } } return(timeSignatureEvents); }
public IMessage getMessage(MetaEvent metaEvent) { switch (metaEvent.MetaEventType) { case SetTempo: TempoEvent tempoEvent = (TempoEvent)metaEvent; TempoMetaMessage message = TempoMetaMessage(tempoEvent.Tempo, tempoEvent.AbsoluteTime); return(message); case TimeSignature: TimeSignatureEvent timeSignatureEvent = (TimeSignatureEvent)metaEvent; TimeSignatureMetaMessage message = TimeSignatureMetaMessage(timeSignatureEvent.Numerator, timeSignatureEvent.Numerator, timeSignatureEvent.AbsoluteTime); return(message); case KeySignature: KeySignatureEvent keySignatureEvent = (KeySignatureEvent)metaEvent; TimeSignatureMetaMessage message = TimeSignatureMetaMessage((sbyte)keySignatureEvent.SharpsFlats, (byte)keySignatureEvent.MajorMinor, timeSignatureEvent.AbsoluteTime); return(message); default: return(null); // TODO remaining MetaMessage types } }
public void ProcessTimeSignatures(MidiEventCollection midi) { // This is way easier if these have already been consolidated ConsolidateTimeTracks(midi); var timeSigTrackNo = midi.FindTrackNumberByName(TrackName.InputTimeSig.ToString()); if (timeSigTrackNo == -1) { AddInfo($"No '{TrackName.InputTimeSig}' track"); return; } var timeEvents = midi[midi.FindTrackNumberByName(TrackName.TempoMap.ToString())]; var inputTimeSignatureEvents = midi[timeSigTrackNo].OfType <NoteOnEvent>(); var groups = inputTimeSignatureEvents.GroupBy(e => e.AbsoluteTime); var error = false; foreach (var pair in groups) { var time = pair.Key; // The higher velocity value is the numerator (top) // And the lower velocity value is the denominator (bottom) var sorted = pair.OrderByDescending(e => e.Velocity).ToArray(); if (sorted.Length != 2) { error = true; var detail = string.Join(", ", sorted.Select(e => $"<{e.NoteName} ({e.NoteNumber}), Velocity: {e.Velocity}>")); AddError($"Incorrect number of time signature notes at {GetBarInfo(midi, time)}: {detail}"); continue; } if (sorted[0].Velocity == sorted[1].Velocity) { error = true; var detail = string.Join(", ", sorted.Select(e => $"<{e.NoteName} ({e.NoteNumber}), Velocity: {e.Velocity}>")); AddError($"Multiple notes with the same velocity at {GetBarInfo(midi, time)}: {detail}"); continue; } var numerator = sorted[0].NoteNumber; int denominator; if (!TryConvertToDenominator(sorted[1].NoteNumber, out denominator)) { error = true; AddError($"Invalid denominator note '{sorted[1].NoteNumber}' at {time}"); continue; } var timeSigEvent = new TimeSignatureEvent(time, numerator, denominator, TicksInClick, NumberOfThirtySecondNotesInQuarterNote); var existingTimeSigEvent = timeEvents.OfType <TimeSignatureEvent>().SingleOrDefault(e => e.AbsoluteTime == time); if (existingTimeSigEvent != null) { timeEvents.Remove(existingTimeSigEvent); } timeEvents.Add(timeSigEvent); } if (error) { throw new InvalidOperationException("Invalid time signature input"); } // Clean up input track midi.RemoveTrack(timeSigTrackNo); UpdateTrackEnd(timeEvents, timeEvents.OrderBy(e => e.AbsoluteTime).Last().AbsoluteTime); // TODO: If there is no TimeSignatureEvent or TempoEvent at 0, wig out }
public Mid ToMid() { Mid mid = new Mid(); mid.Type = Mid.MidiType.Uniform; mid.Division = Division; Mid.Track beat = new Mid.Track(); beat.Events.Add(new Mid.MetaEvent() { DeltaTime = 0, Type = 0x03, Data = (Name == null || Name.Length == 0) ? Util.Encoding.GetBytes("rawksd") : Util.Encoding.GetBytes(Name) }); List <Event> events = new List <Event>(); events.AddRange(BPM.ToArray()); events.AddRange(Signature.ToArray()); events.Sort(new EventComparer()); ulong delta = 0; foreach (Event e in events) { if (e is TimeSignatureEvent) { TimeSignatureEvent sig = e as TimeSignatureEvent; beat.Events.Add(new Mid.MetaEvent() { DeltaTime = (uint)(sig.Time - delta), Type = 0x58, Data = new byte[] { sig.Numerator, sig.Denominator, sig.Metronome, sig.NumberOf32ndNotes } }); } else if (e is TempoEvent) { TempoEvent bpm = e as TempoEvent; byte[] mpqn = new byte[3]; Array.Copy(BigEndianConverter.GetBytes(bpm.MicrosecondsPerBeat), 1, mpqn, 0, 3); beat.Events.Add(new Mid.MetaEvent() { DeltaTime = (uint)(bpm.Time - delta), Type = 0x51, Data = mpqn }); } delta = e.Time; } beat.Events.Add(new Mid.MetaEvent() { DeltaTime = 0, Type = 0x2F, Data = new byte[0] }); mid.Tracks.Add(beat); foreach (Track t in Tracks) { events.Clear(); t.Comments.ForEach(e => { if (e.Type == TextEvent.TextEventType.Unknown) { e.Type = TextEvent.TextEventType.Comment; } }); t.Lyrics.ForEach(e => { if (e.Type == TextEvent.TextEventType.Unknown) { e.Type = TextEvent.TextEventType.Lyric; } }); t.Markers.ForEach(e => { if (e.Type == TextEvent.TextEventType.Unknown) { e.Type = TextEvent.TextEventType.Marker; } }); events.AddRange(t.Notes.ToArray()); events.AddRange(t.Comments.ToArray()); events.AddRange(t.Markers.ToArray()); events.AddRange(t.Lyrics.ToArray()); events.Sort(new EventComparer()); delta = 0; Mid.Track track = new Mid.Track(); track.Events.Add(new Mid.MetaEvent() { DeltaTime = 0, Type = 0x03, Data = Util.Encoding.GetBytes(t.Name) }); List <NoteEvent> OpenNotes = new List <NoteEvent>(); foreach (Event e in events) { __fuck_labels_opennotesagain: foreach (NoteEvent n in OpenNotes) { if (n.Time + n.Duration <= e.Time) { track.Events.Add(new Mid.ChannelEvent() { DeltaTime = (uint)(n.Time + n.Duration - delta), Channel = n.Channel, Type = 0x8, Parameter1 = n.Note, Parameter2 = n.ReleaseVelocity }); delta = n.Time + n.Duration; OpenNotes.Remove(n); goto __fuck_labels_opennotesagain; // Yeah, too lazy to make a ToRemove list } } if (e is NoteEvent) { NoteEvent n = e as NoteEvent; NoteEvent overlap = OpenNotes.Find(n2 => n2.Note == n.Note); if (overlap != null) // Stretch the open note over the colliding note { overlap.Duration = Math.Max(overlap.Duration, n.Time + n.Duration - overlap.Time); OpenNotes.Sort(new NoteEventComparer()); continue; } else { OpenNotes.Insert(0, n); OpenNotes.Sort(new NoteEventComparer()); track.Events.Add(new Mid.ChannelEvent() { DeltaTime = (uint)(n.Time - delta), Channel = n.Channel, Type = 0x9, Parameter1 = n.Note, Parameter2 = n.Velocity }); } } else if (e is TextEvent) { TextEvent l = e as TextEvent; track.Events.Add(new Mid.MetaEvent() { DeltaTime = (uint)(l.Time - delta), Type = (byte)l.Type, Data = Util.Encoding.GetBytes(l.Text) }); } else if (e is TextEvent) { TextEvent c = e as TextEvent; track.Events.Add(new Mid.MetaEvent() { DeltaTime = (uint)(c.Time - delta), Type = 0x1, Data = Util.Encoding.GetBytes(c.Text) }); } delta = e.Time; } foreach (NoteEvent n in OpenNotes) { track.Events.Add(new Mid.ChannelEvent() { DeltaTime = (uint)(n.Time + n.Duration - delta), Channel = n.Channel, Type = 0x8, Parameter1 = n.Note, Parameter2 = n.ReleaseVelocity }); delta = n.Time + n.Duration; } track.Events.Add(new Mid.MetaEvent() { DeltaTime = 0, Type = 0x2F, Data = new byte[0] }); mid.Tracks.Add(track); } return(mid); }
void UpdateBars() { for (int i = 0; i < tracks.Count; i++) { while (tracks [i] [eventPos [i]].AbsoluteTime <= ticks) { if (endOfTrack [i]) { break; } midiEvent = tracks [i] [eventPos [i]]; switch (midiEvent.CommandCode) { case MidiCommandCode.MetaEvent: metaEvent = (midiEvent as MetaEvent); switch (metaEvent.MetaEventType) { case MetaEventType.KeySignature: keyMajorMinor = (metaEvent as KeySignatureEvent).MajorMinor; Debug.Log("MAJOR or MINOR: " + keyMajorMinor); keySharpsFlats = (metaEvent as KeySignatureEvent).SharpsFlats; Debug.Log("SIGNATURE : " + keySharpsFlats); break; case MetaEventType.SequenceTrackName: Debug.Log("TrackName : " + (metaEvent as TextEvent).Text); break; case MetaEventType.SetTempo: TempoEvent tempoEvent = (midiEvent as TempoEvent); tempoOriginal = (float)tempoEvent.Tempo; if (!tempoCustom) { tempo = tempoOriginal; } break; case MetaEventType.SmpteOffset: break; case MetaEventType.TextEvent: break; case MetaEventType.TimeSignature: TimeSignatureEvent signatureEvent = (midiEvent as TimeSignatureEvent); timeSignatureNumerator = signatureEvent.Numerator; _timeSignatureDenominator = signatureEvent.Denominator; timeSignatureDenominator = (int)Mathf.Pow(2, _timeSignatureDenominator); break; case MetaEventType.EndTrack: break; } break; } if (eventPos [i] >= tracks [i].Count - 1) { endOfTrack [i] = true; bool endOfFile = true; for (int k = 0; k < tracks.Count; k++) { if (!endOfTrack [k]) { endOfFile = false; break; } } if (endOfFile) { state = State.Finished; ticks = ticks - lastDeltaTicks; totalTime = time - lastDeltaTime; Bar lastBar = bars.Last(); lastBar.timeDuration = time - lastBar.time; lastBar.ticksDuration = ticks - lastBar.ticks; return; } break; } eventPos [i] = eventPos [i] == tracks [i].Count - 1 ? eventPos [i] : eventPos [i] + 1; } } if (beatCount != (int)(ticks / PPQN / (4f / timeSignatureDenominator)) + 1) { beat = beatCount % (int)timeSignatureNumerator + 1; beatCount = (int)(ticks / PPQN / (4f / timeSignatureDenominator)) + 1; if (beat == 1) { Bar bar = new Bar() { time = this.time, ticks = this.ticks, tempo = this.tempo, timeSignatureNumerator = this.timeSignatureNumerator, timeSignatureDenominator = this.timeSignatureDenominator, majorMinor = this.keyMajorMinor, sharpsFlats = this.keySharpsFlats }; if (bars.Count > 0) { Bar lastBar = bars.Last(); lastBar.timeDuration = time - lastDeltaTime - lastBar.time; lastBar.ticksDuration = ticks - lastDeltaTicks - lastBar.ticks; } bar.eventPos = new int[eventPos.Length]; bar.endOfTrack = new bool[endOfTrack.Length]; for (int i = 0; i < bar.eventPos.Length; i++) { bar.eventPos [i] = GetTrackEventPosFromAbsoluteTicks(i, ticks - 100); bar.endOfTrack [i] = endOfTrack [i]; } bars.Add(bar); } } deltaTime = deltaTimeResolution; periodResolution = PPQN * 1000f * deltaTime * MicrosecondsPerMillisecond; //ticksPerClock = PPQN / PPQNMinValue; deltaTicks = (fractionalTicks + periodResolution) / tempoTicks; fractionalTicks += periodResolution - deltaTicks * tempoTicks; ticks += deltaTicks; time += deltaTime; lastTime = time; lastDeltaTime = deltaTime; lastDeltaTicks = deltaTicks; }
public void Extractor() { int pan = 0; int noteLength = 0; int restLength = 0; int tempLength = 0; int totalLength = 0; //the sum of noteLength and restLength. int trackVolume = 1; //volume of the MIDI track, can change throughout the track int velocity = 0; // velocity of the MIDI note int note = -1; //stores the value of the next note; -1 is the starting note and is a "rest" that might print only in the beginning; bool flagNote = false; int[] MIDILength = new int[] { 0, 0, 0, 0 }; //checks if the out.asm file already exists and clears its contents if (File.Exists(string.Concat(directoryPath, ASMFileName, ".asm"))) { FileStream fileStream = File.Open(string.Concat(directoryPath, ASMFileName, ".asm"), FileMode.Open); fileStream.SetLength(0); fileStream.Close(); } var midifile = MidiFile.Read(directoryPath + midiFileName + "." + midiFileExtension); var trackChuncks = midifile.GetTrackChunks(); // contains the information for all tracks if (TempoTrack) { NumberOfTracks = trackChuncks.Count() - 1; TrackNumber = -1; } else { NumberOfTracks = trackChuncks.Count(); } //finds the TimeDivision and the number of tracks of the MIDI file string[] tempDivision = midifile.TimeDivision.ToString().Split(' '); TimeDivision = Int32.Parse(tempDivision[0]); for (int k = 0; k < allowedNotetypes.Length; k++) { unitaryLengthArray[k] = Convert.ToInt32((double)TimeDivision / (48 / allowedNotetypes[k])); } unitaryLength = unitaryLengthArray[BaseNotetypeLocation]; AllTrackList = new List <MIDINote> [NumberOfTracks]; //creates the AllTrackList with NumberOfTracks Length // Reads each track in sequence foreach (var track in trackChuncks) { TrackNumber++; trackVolume = 1; //resets trackvolume for the new track //loops through events foreach (MidiEvent Level2 in track.Events) { //get the Delta Time of the event tempLength = (int)Level2.DeltaTime; totalLength = noteLength + tempLength + restLength; switch (Level2.EventType.ToString()) { case "ControlChange": { ControlChangeEvent TempEvent = (ControlChangeEvent)Level2; //tests and changes stereopanning if (TempEvent.ControlNumber == 10) { pan = TempEvent.ControlValue; } //sets new trackvolume to define the intensity of this track. Can vary multiple times during the same music. if (TempEvent.ControlNumber == 7) { trackVolume = TempEvent.ControlValue; } break; } //only relevant for the first track case "TimeSignature": { TimeSignatureEvent TempEvent = (TimeSignatureEvent)Level2; timeSignature = TempEvent.Numerator * 16 / TempEvent.Denominator; break; } case "SetTempo": { SetTempoEvent TempEvent = (SetTempoEvent)Level2; Tempo = Convert.ToInt32(TempEvent.MicrosecondsPerQuarterNote) / 3138;; break; } case "NoteOn": { //register the currently "saved" note // we are on a rest NoteEvent TempEvent = (NoteEvent)Level2; flagNote = true; restLength += tempLength; if ((restLength >= unitaryLength & TrackNumber != 4) || (restLength >= unitaryLength * 16)) //the noise channel only prints rests if its bigger than 16 times the UL { if (IgnoreRests) { NoteListTemp.Add(new MIDINote(noteLength + restLength, MIDILength[TrackNumber - 1], note, pan, velocity, trackVolume)); } else { NoteListTemp.Add(new MIDINote(noteLength, MIDILength[TrackNumber - 1], note, pan, velocity, trackVolume)); NoteListTemp.Add(new MIDINote(restLength, MIDILength[TrackNumber - 1] + noteLength, 0, pan, velocity, trackVolume)); } } else { NoteListTemp.Add(new MIDINote(totalLength, MIDILength[TrackNumber - 1], note, pan, velocity, trackVolume)); } //i++; //debug //NoteListTemp.ElementAt(i-1).ShowNotes(); //debug MIDILength[TrackNumber - 1] += totalLength; noteLength = restLength = tempLength = totalLength = 0; //setup for the next note note = TempEvent.NoteNumber; velocity = TempEvent.Velocity; break; } case "NoteOff": { //NoteEvent TempEvent = (NoteEvent)Level2; flagNote = true; noteLength += tempLength; break; } default: { break; } } if (!flagNote & tempLength > unitaryLength) { restLength += tempLength; } else if (!flagNote) { noteLength += tempLength; } flagNote = false; } //last note print if (TrackNumber > 0) { NoteListTemp.Add(new MIDINote(totalLength, MIDILength[TrackNumber - 1], note, pan, velocity, trackVolume)); } //We've reached the end of the track noteLength = restLength = totalLength = 0; note = -1; if (TrackNumber > 0) { AllTrackList[TrackNumber - 1] = new List <MIDINote>(NoteListTemp); //for(int i=0;i<NoteListTemp.Count;i++) //{ // Console.WriteLine(NoteListTemp.ElementAt(i)); //} NoteListTemp.Clear(); } } }
/// <summary> /// Return information about a midifile : patch change, copyright, ... /// </summary> /// <param name="pathfilename"></param> /// <param name="Info"></param> static public void GeneralInfo(string pathfilename, BuilderInfo Info) { try { int NumberBeatsMeasure; int NumberQuarterBeat; Debug.Log("Open midifile :" + pathfilename); MidiLoad midifile = new MidiLoad(); midifile.Load(pathfilename); if (midifile != null) { Info.Add(string.Format("Format: {0}", midifile.midifile.FileFormat)); Info.Add(string.Format("Tracks: {0}", midifile.midifile.Tracks)); Info.Add(string.Format("Ticks Quarter Note: {0}", midifile.midifile.DeltaTicksPerQuarterNote)); //if (false) { foreach (TrackMidiEvent trackEvent in midifile.MidiSorted) { if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOn) { // Not used //if (((NoteOnEvent)trackEvent.Event).OffEvent != null) //{ // //infoTrackMidi[e.Channel].Events.Add((NoteOnEvent)e); // NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event; //} } else if (trackEvent.Event.CommandCode == MidiCommandCode.NoteOff) { Debug.Log("NoteOff"); } else if (trackEvent.Event.CommandCode == MidiCommandCode.ControlChange) { // Not used //ControlChangeEvent controlchange = (ControlChangeEvent)e; //Debug.Log(string.Format("CtrlChange Track:{0} Channel:{1,2:00} {2}", track, e.Channel, controlchange.ToString())); } else if (trackEvent.Event.CommandCode == MidiCommandCode.PatchChange) { PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("PatchChange {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch)), 2); } else if (trackEvent.Event.CommandCode == MidiCommandCode.MetaEvent) { MetaEvent meta = (MetaEvent)trackEvent.Event; switch (meta.MetaEventType) { case MetaEventType.SetTempo: TempoEvent tempo = (TempoEvent)meta; Info.Add(BuildInfoTrack(trackEvent) + string.Format("SetTempo Tempo:{0} MicrosecondsPerQuarterNote:{1}", Math.Round(tempo.Tempo, 0), tempo.MicrosecondsPerQuarterNote), 2); //tempo.Tempo break; case MetaEventType.TimeSignature: TimeSignatureEvent timesig = (TimeSignatureEvent)meta; // Numerator: counts the number of beats in a measure. // For example a numerator of 4 means that each bar contains four beats. // Denominator: number of quarter notes in a beat.0=ronde, 1=blanche, 2=quarter, 3=eighth, etc. // Set default value NumberBeatsMeasure = timesig.Numerator; NumberQuarterBeat = System.Convert.ToInt32(System.Math.Pow(2, timesig.Denominator)); Info.Add(BuildInfoTrack(trackEvent) + string.Format("TimeSignature Beats Measure:{0} Beat Quarter:{1}", NumberBeatsMeasure, NumberQuarterBeat), 2); break; case MetaEventType.SequenceTrackName: // Sequence / Track Name case MetaEventType.ProgramName: case MetaEventType.TrackInstrumentName: // Track instrument name case MetaEventType.TextEvent: // Text event case MetaEventType.Copyright: // Copyright Info.Add(BuildInfoTrack(trackEvent) + ((TextEvent)meta).Text, 1); break; case MetaEventType.Lyric: // lyric case MetaEventType.Marker: // marker case MetaEventType.CuePoint: // cue point case MetaEventType.DeviceName: //Info.Add(BuildInfoTrack(trackEvent) + string.Format("{0} '{1}'", meta.MetaEventType.ToString(), ((TextEvent)meta).Text)); break; } } else { // Other midi event //Debug.Log(string.Format("Track:{0} Channel:{1,2:00} CommandCode:{2,3:000} AbsoluteTime:{3,6:000000}", track, e.Channel, e.CommandCode.ToString(), e.AbsoluteTime)); } } } //else DebugMidiSorted(midifile.MidiSorted); } else { Info.Add("Error reading midi file"); } } catch (System.Exception ex) { MidiPlayerGlobal.ErrorDetail(ex); } }
private static Tuple <Option <MidiEvent>, int, byte> NextEvent(List <byte> trackData, int startIndex, byte lastMidiChannel) { var i = startIndex - 1; MidiEvent midiEvent = null; { int deltaTime; { var lengthTemp = new List <byte>(); do { i += 1; lengthTemp.Add(trackData.ElementAt(i)); } while (trackData.ElementAt(i) > 0x7F); deltaTime = VariableLengthUtil.decode_to_int(lengthTemp); } i += 1; var eventTypeValue = trackData.ElementAt(i); // MIDI Channel Events if ((eventTypeValue & 0xF0) < 0xF0) { var midiChannelEventType = (byte)(eventTypeValue & 0xF0); var midiChannel = (byte)(eventTypeValue & 0x0F); i += 1; var parameter1 = trackData.ElementAt(i); byte parameter2; // One or two parameter type switch (midiChannelEventType) { // One parameter types case 0xC0: midiEvent = new ProgramChangeEvent(deltaTime, midiChannel, parameter1); lastMidiChannel = midiChannel; break; case 0xD0: midiEvent = new ChannelAftertouchEvent(deltaTime, midiChannel, parameter1); lastMidiChannel = midiChannel; break; // Two parameter types case 0x80: i += 1; parameter2 = trackData.ElementAt(i); midiEvent = new NoteOffEvent(deltaTime, midiChannel, parameter1, parameter2); lastMidiChannel = midiChannel; break; case 0x90: i += 1; parameter2 = trackData.ElementAt(i); midiEvent = new NoteOnEvent(deltaTime, midiChannel, parameter1, parameter2); lastMidiChannel = midiChannel; break; case 0xA0: i += 1; parameter2 = trackData.ElementAt(i); midiEvent = new NoteAftertouchEvent(deltaTime, midiChannel, parameter1, parameter2); lastMidiChannel = midiChannel; break; case 0xB0: i += 1; parameter2 = trackData.ElementAt(i); midiEvent = new ControllerEvent(deltaTime, midiChannel, parameter1, parameter2); lastMidiChannel = midiChannel; break; case 0xE0: i += 1; parameter2 = trackData.ElementAt(i); midiEvent = new PitchBendEvent(deltaTime, midiChannel, parameter1, parameter2); lastMidiChannel = midiChannel; break; // Might be a Control Change Messages LSB default: midiEvent = new ControllerEvent(deltaTime, lastMidiChannel, eventTypeValue, parameter1); break; } i += 1; } // Meta Events else if (eventTypeValue == 0xFF) { i += 1; var metaEventType = trackData.ElementAt(i); i += 1; var metaEventLength = trackData.ElementAt(i); i += 1; var metaEventData = Enumerable.Range(i, metaEventLength).Select(trackData.ElementAt).ToArray(); switch (metaEventType) { case 0x00: midiEvent = new SequenceNumberEvent(BitConverter.ToUInt16(metaEventData.Reverse().ToArray(), 0)); break; case 0x01: midiEvent = new TextEvent(deltaTime, StringEncoder.GetString(metaEventData)); break; case 0x02: midiEvent = new CopyrightNoticeEvent(StringEncoder.GetString(metaEventData)); break; case 0x03: midiEvent = new SequenceOrTrackNameEvent(StringEncoder.GetString(metaEventData)); break; case 0x04: midiEvent = new InstrumentNameEvent(deltaTime, StringEncoder.GetString(metaEventData)); break; case 0x05: midiEvent = new LyricsEvent(deltaTime, StringEncoder.GetString(metaEventData)); break; case 0x06: midiEvent = new MarkerEvent(deltaTime, StringEncoder.GetString(metaEventData)); break; case 0x07: midiEvent = new CuePointEvent(deltaTime, StringEncoder.GetString(metaEventData)); break; case 0x20: midiEvent = new MIDIChannelPrefixEvent(deltaTime, metaEventData[0]); break; case 0x2F: midiEvent = new EndOfTrackEvent(deltaTime); break; case 0x51: var tempo = (metaEventData[2] & 0x0F) + ((metaEventData[2] & 0xF0) * 16) + ((metaEventData[1] & 0x0F) * 256) + ((metaEventData[1] & 0xF0) * 4096) + ((metaEventData[0] & 0x0F) * 65536) + ((metaEventData[0] & 0xF0) * 1048576); midiEvent = new SetTempoEvent(deltaTime, tempo); break; case 0x54: midiEvent = new SMPTEOffsetEvent(deltaTime, metaEventData[0], metaEventData[1], metaEventData[2], metaEventData[3], metaEventData[4]); break; case 0x58: midiEvent = new TimeSignatureEvent(deltaTime, metaEventData[0], metaEventData[1], metaEventData[2], metaEventData[3]); break; case 0x59: midiEvent = new KeySignatureEvent(deltaTime, metaEventData[0], metaEventData[1]); break; case 0x7F: midiEvent = new SequencerSpecificEvent(deltaTime, metaEventData); break; } i += metaEventLength; } // System Exclusive Events else if (eventTypeValue == 0xF0 || eventTypeValue == 0xF7) { var lengthTemp = new List <byte>(); do { i += 1; lengthTemp.Add(trackData.ElementAt(i)); } while (trackData.ElementAt(i) > 0x7F); var eventLength = VariableLengthUtil.decode_to_int(lengthTemp); i += 1; var eventData = Enumerable.Range(i, eventLength).Select(trackData.ElementAt); midiEvent = new SysexEvent(deltaTime, eventTypeValue, eventData); i += eventLength; } } return(midiEvent != null ? new Tuple <Option <MidiEvent>, int, byte>(new Some <MidiEvent>(midiEvent), i - startIndex, lastMidiChannel) : new Tuple <Option <MidiEvent>, int, byte>(new None <MidiEvent>(), i - startIndex, lastMidiChannel)); }
/// <summary> /// Return information about a midifile : patch change, copyright, ... /// </summary> /// <param name="pathfilename"></param> /// <param name="Info"></param> static public List <string> GeneralInfo(string pathfilename, bool withNoteOn, bool withNoteOff, bool withControlChange, bool withPatchChange, bool withAfterTouch, bool withMeta, bool withOthers) { List <string> Info = new List <string>(); try { int NumberBeatsMeasure; int NumberQuarterBeat; MidiLoad midifile = new MidiLoad(); midifile.KeepNoteOff = withNoteOff; midifile.MPTK_Load(pathfilename); if (midifile != null) { Info.Add(string.Format("Format: {0}", midifile.midifile.FileFormat)); Info.Add(string.Format("Tracks: {0}", midifile.midifile.Tracks)); Info.Add(string.Format("Events count: {0}", midifile.MidiSorted.Count())); Info.Add(string.Format("Duration: {0} ({1} seconds) {2} Ticks", midifile.MPTK_RealDuration, midifile.MPTK_RealDuration.TotalSeconds, midifile.MPTK_TickLast)); Info.Add(string.Format("Initial Tempo: {0,0:F2} BPM", midifile.MPTK_InitialTempo)); Info.Add(string.Format("Beats in a measure: {0}", midifile.MPTK_NumberBeatsMeasure)); Info.Add(string.Format("Quarters count in a beat:{0}", midifile.MPTK_NumberQuarterBeat)); Info.Add(string.Format("Ticks per Quarter Note: {0}", midifile.midifile.DeltaTicksPerQuarterNote)); Info.Add(""); //if (false) { foreach (TrackMidiEvent trackEvent in midifile.MidiSorted) { switch (trackEvent.Event.CommandCode) { case MidiCommandCode.NoteOn: if (withNoteOn) { if (((NoteOnEvent)trackEvent.Event).OffEvent != null) { NoteOnEvent noteon = (NoteOnEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("NoteOn {0,3} ({1,3}) Len:{2,3} Vel:{3,3}", noteon.NoteName, noteon.NoteNumber, noteon.NoteLength, noteon.Velocity)); } } break; case MidiCommandCode.NoteOff: if (withNoteOff) { NoteEvent noteoff = (NoteEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("NoteOff {0,3} ({1,3}) Vel:{2,3}", noteoff.NoteName, noteoff.NoteNumber, noteoff.Velocity)); } break; case MidiCommandCode.PitchWheelChange: if (withOthers) { PitchWheelChangeEvent aftertouch = (PitchWheelChangeEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("PitchWheelChange {0,3}", aftertouch.Pitch)); } break; case MidiCommandCode.KeyAfterTouch: if (withAfterTouch) { NoteEvent aftertouch = (NoteEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("KeyAfterTouch {0,3} ({1,3}) Pressure:{2,3}", aftertouch.NoteName, aftertouch.NoteNumber, aftertouch.Velocity)); } break; case MidiCommandCode.ChannelAfterTouch: if (withAfterTouch) { ChannelAfterTouchEvent aftertouch = (ChannelAfterTouchEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("ChannelAfterTouch Pressure:{0,3}", aftertouch.AfterTouchPressure)); } break; case MidiCommandCode.ControlChange: if (withControlChange) { ControlChangeEvent controlchange = (ControlChangeEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("ControlChange {0,3} ({1,3}) Value:{2,3}", controlchange.Controller, controlchange.Controller, controlchange.ControllerValue)); } break; case MidiCommandCode.PatchChange: if (withPatchChange) { PatchChangeEvent change = (PatchChangeEvent)trackEvent.Event; Info.Add(BuildInfoTrack(trackEvent) + string.Format("PatchChange {0,3:000} {1}", change.Patch, PatchChangeEvent.GetPatchName(change.Patch))); } break; case MidiCommandCode.MetaEvent: if (withMeta) { MetaEvent meta = (MetaEvent)trackEvent.Event; switch (meta.MetaEventType) { case MetaEventType.SetTempo: TempoEvent tempo = (TempoEvent)meta; Info.Add(BuildInfoTrack(trackEvent) + string.Format("SetTempo Tempo:{0} MicrosecondsPerQuarterNote:{1}", Math.Round(tempo.Tempo, 0), tempo.MicrosecondsPerQuarterNote)); //tempo.Tempo break; case MetaEventType.TimeSignature: TimeSignatureEvent timesig = (TimeSignatureEvent)meta; // Numerator: counts the number of beats in a measure. // For example a numerator of 4 means that each bar contains four beats. // Denominator: number of quarter notes in a beat.0=ronde, 1=blanche, 2=quarter, 3=eighth, etc. // Set default value NumberBeatsMeasure = timesig.Numerator; NumberQuarterBeat = System.Convert.ToInt32(Mathf.Pow(2, timesig.Denominator)); Info.Add(BuildInfoTrack(trackEvent) + string.Format("TimeSignature Beats Measure:{0} Beat Quarter:{1}", NumberBeatsMeasure, NumberQuarterBeat)); break; default: string text = meta is TextEvent ? " '" + ((TextEvent)meta).Text + "'" : ""; Info.Add(BuildInfoTrack(trackEvent) + meta.MetaEventType.ToString() + text); break; } } break; default: // Other midi event if (withOthers) { Info.Add(BuildInfoTrack(trackEvent) + string.Format(" {0} ({1})", trackEvent.Event.CommandCode, (int)trackEvent.Event.CommandCode)); } break; } } } //else DebugMidiSorted(midifile.MidiSorted); } else { Info.Add("Error reading midi file"); } } catch (System.Exception ex) { MidiPlayerGlobal.ErrorDetail(ex); } return(Info); }
bool CallEvents() { if (wordPos < words.Count) { if (wordPos > 0) { if (!words [wordPos].finishFired) { if (words [wordPos].absoluteStartTime <= ticks) { if (OnWordFinished != null) { OnWordFinished(); } words [wordPos].finishFired = true; } } } if (words [wordPos < 0 ? 0 : wordPos].absoluteStartTime <= ticks) { if (OnWord != null) { OnWord(words [wordPos < 0 ? 0 : wordPos]); } wordPos++; } } if (wordOffsetPos < words.Count) { if (wordOffsetPos > 0) { if (!words [wordOffsetPos].finishFired) { if (words [wordOffsetPos].absoluteStartTime + TimeToTicks(wordTimeOffset) + TimeToTicks(wordTimeFinishedOffset) <= ticks) { if (OnWordOffsetFinished != null) { OnWordOffsetFinished(); } words [wordOffsetPos].finishOffsetFired = true; } } } if (words [wordOffsetPos < 0 ? 0 : wordOffsetPos].absoluteStartTime + TimeToTicks(wordTimeOffset) <= ticks) { if (OnWordOffset != null) { OnWordOffset(words [wordOffsetPos < 0 ? 0 : wordOffsetPos]); } wordOffsetPos++; } } if (sentencePos < sentences.Count) { if (sentences [sentencePos < 0 ? 0 : sentencePos].absoluteStartTime + TimeToTicks(senteceTimeOffset) <= ticks) { if (OnSentence != null) { OnSentence(sentences [sentencePos < 0 ? 0 : sentencePos]); } sentencePos++; } } if (versePos < verses.Count) { if (verses [versePos < 0 ? 0 : versePos].absoluteStartTime + TimeToTicks(versetTimeOffset) <= ticks) { if (OnVerse != null) { OnVerse(verses [versePos < 0 ? 0 : versePos]); } versePos++; } } for (int i = 0; i < tracks.Count; i++) { while (tracks [i] [eventPos [i]].AbsoluteTime <= ticks) { if (endOfTrack [i]) { break; } midiEvent = tracks [i] [eventPos [i]]; command = midiEvent.CommandCode; if (command == MidiCommandCode.NoteOn && midiEvent.Data2 == 0) { command = MidiCommandCode.NoteOff; } if (midiOut) { if (!muteTrack [i]) { MidiOut.SendShortMessage((forceTrackAsChannel ? i : (midiEvent.Channel - 1)) + (int)command, midiEvent.Data1, /*command == MidiCommandCode.NoteOn ? (int)Mathf.Clamp(midiEvent.Data2 * volume, 0, 127) :*/ midiEvent.Data2); } } if (ShortMessageEvent != null) { ShortMessageEvent((forceTrackAsChannel ? i : (midiEvent.Channel - 1)) + (int)command, midiEvent.Data1, midiEvent.Data2); } switch (midiEvent.CommandCode) { case MidiCommandCode.AutoSensing: break; case MidiCommandCode.ChannelAfterTouch: break; case MidiCommandCode.ContinueSequence: break; case MidiCommandCode.ControlChange: //controlEvent = (midiEvent as ControlChangeEvent); break; case MidiCommandCode.Eox: break; case MidiCommandCode.KeyAfterTouch: break; case MidiCommandCode.MetaEvent: metaEvent = (midiEvent as MetaEvent); switch (metaEvent.MetaEventType) { case MetaEventType.Copyright: Debug.Log("Copyright : " + (metaEvent as TextEvent).Text); break; case MetaEventType.CuePoint: break; case MetaEventType.DeviceName: break; case MetaEventType.EndTrack: break; case MetaEventType.KeySignature: keyMajorMinor = (metaEvent as KeySignatureEvent).MajorMinor; Debug.Log("MAJOR or MINOR: " + keyMajorMinor); keySharpsFlats = (metaEvent as KeySignatureEvent).SharpsFlats; Debug.Log("SIGNATURE : " + keySharpsFlats); break; case MetaEventType.Lyric: break; case MetaEventType.Marker: break; case MetaEventType.MidiChannel: break; case MetaEventType.MidiPort: break; case MetaEventType.ProgramName: Debug.Log("Program Name : " + (metaEvent as TextEvent).Text); break; case MetaEventType.SequencerSpecific: //SequencerSpecificEvent sequencerEvent = midiEvent as SequencerSpecificEvent; break; case MetaEventType.SequenceTrackName: Debug.Log("TrackName : " + (metaEvent as TextEvent).Text); break; case MetaEventType.SetTempo: TempoEvent tempoEvent = (midiEvent as TempoEvent); tempoOriginal = (float)tempoEvent.Tempo; if (!tempoCustom) { tempo = tempoOriginal; } if (OnTempoChange != null) { OnTempoChange(tempo); } break; case MetaEventType.SmpteOffset: break; case MetaEventType.TextEvent: break; case MetaEventType.TimeSignature: TimeSignatureEvent signatureEvent = (midiEvent as TimeSignatureEvent); timeSignatureNumerator = signatureEvent.Numerator; _timeSignatureDenominator = signatureEvent.Denominator; timeSignatureDenominator = (int)Mathf.Pow(2, _timeSignatureDenominator); break; case MetaEventType.TrackInstrumentName: Debug.Log("Instrument Name : " + (metaEvent as TextEvent).Text); break; case MetaEventType.TrackSequenceNumber: break; default: break; } break; case MidiCommandCode.NoteOn: break; case MidiCommandCode.NoteOff: break; case MidiCommandCode.PatchChange: break; case MidiCommandCode.PitchWheelChange: break; case MidiCommandCode.StartSequence: break; case MidiCommandCode.StopSequence: break; case MidiCommandCode.Sysex: break; case MidiCommandCode.TimingClock: break; } if (eventPos [i] >= tracks [i].Count - 1) { endOfTrack [i] = true; bool endOfFile = true; for (int k = 0; k < tracks.Count; k++) { if (!endOfTrack [k]) { endOfFile = false; break; } } if (endOfFile) { ticks = ticks - lastDeltaTicks; time = time - lastDeltaTime; if (repeatBarSelection) { cancelUpdate = true; SetBar(startBar, true); return(false); } else { cancelUpdate = true; midiFinished = true; return(false); } } break; } eventPos [i] = eventPos [i] == tracks [i].Count - 1 ? eventPos [i] : eventPos [i] + 1; } } return(true); }
public TimeSignatureEventLabel(TimeSignatureEvent timeSignatureEvent) : base(timeSignatureEvent) { }
private void CreateTrackZeroEvents(List<MidiEvent> trackZeroEvents, MidiFile midiFile, long startAbsoluteTime, long endAbsoluteTime, bool includeAllTrackEvents) { MetaEvent tempoEvent = null; MetaEvent keySignatureEvent = null; MetaEvent timeSignatureEvent = null; bool gotAStartTempo = false; bool gotAStartKeySig = false; bool gotAStartTimeSig = false; for (int track = 0; track < ((includeAllTrackEvents) ? midiFile.Tracks : 1); track++) { foreach (MidiEvent midiEvent in midiFile.Events[track]) { if ((midiEvent.AbsoluteTime >= startAbsoluteTime) && (midiEvent.AbsoluteTime < endAbsoluteTime)) { bool exclude = false; MetaEvent metaEvent = midiEvent as MetaEvent; if (metaEvent != null) { if (metaEvent.MetaEventType == MetaEventType.EndTrack) { // we'll add our own exclude = true; } if (metaEvent.AbsoluteTime == startAbsoluteTime) { switch (metaEvent.MetaEventType) { case MetaEventType.SetTempo: gotAStartTempo = true; break; case MetaEventType.KeySignature: gotAStartKeySig = true; break; case MetaEventType.TimeSignature: gotAStartTimeSig = true; break; case MetaEventType.Marker: // already done this elsewhere exclude = true; break; case MetaEventType.TextEvent: // exclude if text events as markers is on exclude = settings.TextEventMarkers; break; } } } else { exclude = !includeAllTrackEvents; } if (!exclude) { AddMidiEvent(midiEvent, trackZeroEvents, endAbsoluteTime); } } else if (midiEvent.AbsoluteTime < startAbsoluteTime) { // TODO: perhaps look out for a patch change too MetaEvent metaEvent = midiEvent as MetaEvent; if (metaEvent != null) { switch (metaEvent.MetaEventType) { case MetaEventType.TextEvent: case MetaEventType.Copyright: case MetaEventType.SequenceTrackName: //TextEvent te = (TextEvent)metaEvent; //trackZeroEvents.Add(new TextEvent(te.Text, metaEvent.MetaEventType, startAbsoluteTime)); break; case MetaEventType.KeySignature: KeySignatureEvent kse = (KeySignatureEvent)metaEvent; keySignatureEvent = new KeySignatureEvent(kse.SharpsFlats, kse.MajorMinor, startAbsoluteTime); break; case MetaEventType.SetTempo: tempoEvent = new TempoEvent(((TempoEvent)metaEvent).MicrosecondsPerQuarterNote, startAbsoluteTime); ; break; case MetaEventType.TimeSignature: TimeSignatureEvent tse = (TimeSignatureEvent)metaEvent; timeSignatureEvent = new TimeSignatureEvent(tse.Numerator, tse.Denominator, tse.TicksInMetronomeClick, tse.No32ndNotesInQuarterNote, startAbsoluteTime); break; case MetaEventType.TrackSequenceNumber: // TODO: needed? break; case MetaEventType.TrackInstrumentName: case MetaEventType.Lyric: case MetaEventType.CuePoint: case MetaEventType.Marker: case MetaEventType.SequencerSpecific: case MetaEventType.DeviceName: case MetaEventType.ProgramName: case MetaEventType.SmpteOffset: case MetaEventType.EndTrack: // ignore these break; default: //System.Diagnostics.Debug.Assert(false, String.Format("Unexpected meta event type {0}", metaEvent)); break; } } } } } if ((tempoEvent != null) && (!gotAStartTempo)) trackZeroEvents.Add(tempoEvent); if ((keySignatureEvent != null) && (!gotAStartKeySig)) trackZeroEvents.Add(keySignatureEvent); if ((timeSignatureEvent != null) && (!gotAStartTimeSig)) trackZeroEvents.Add(timeSignatureEvent); // add an end track marker trackZeroEvents.Sort(new MidiEventComparer()); trackZeroEvents.Add(new MetaEvent(MetaEventType.EndTrack,0,trackZeroEvents[trackZeroEvents.Count-1].AbsoluteTime)); }
protected bool Equals(TimeSignatureEvent other) { return base.Equals(other) && Numerator == other.Numerator && Denominator == other.Denominator; }
/// <summary> /// Generates the list of bar entities of a midi file /// </summary> /// <param name="base64encodedMidiFile"></param> /// <returns></returns> public static List <Bar> GetBarsOfSong(string base64encodedMidiFile, SongSimplification songSimplification) { List <Bar> retObj = new List <Bar>(); int barNumber = 1; var ticksPerBeat = GetTicksPerBeatOfSong(base64encodedMidiFile); var songDurationInTicks = GetSongDurationInTicks(base64encodedMidiFile); var timeSignatureEvents = GetEventsOfType(base64encodedMidiFile, MidiEventType.TimeSignature); var setTempoEvents = GetEventsOfType(base64encodedMidiFile, MidiEventType.SetTempo); timeSignatureEvents = ConvertDeltaTimeToAccumulatedTime(timeSignatureEvents); var TempoEvents = QuantizeTempos(ConvertDeltaTimeToAccumulatedTime(setTempoEvents)); //status TimeSignatureEvent currentTimeSignature = new TimeSignatureEvent { Numerator = 4, Denominator = 4 }; if (timeSignatureEvents.Count > 0) { currentTimeSignature = (TimeSignatureEvent)timeSignatureEvents[0]; } int currentTempo = 500000; int timeSigIndex = 0; int tempoIndex = 0; long currentTick = 0; while (currentTick < songDurationInTicks) { if (TempoEvents.Count > 0) { currentTempo = (int)TempoEvents[tempoIndex].MicrosecondsPerQuarterNote; } long timeOfNextTimeSignatureEvent = songDurationInTicks; if (timeSignatureEvents.Count - 1 > timeSigIndex) { timeOfNextTimeSignatureEvent = timeSignatureEvents[timeSigIndex + 1].DeltaTime; } long timeOfNextSetTempoEvent = songDurationInTicks; if (TempoEvents.Count - 1 > tempoIndex) { timeOfNextSetTempoEvent = TempoEvents[tempoIndex + 1].DeltaTime; } long lastTickOfBarToBeAdded = currentTimeSignature.Numerator * ticksPerBeat + currentTick; while ((lastTickOfBarToBeAdded <= timeOfNextTimeSignatureEvent && lastTickOfBarToBeAdded <= timeOfNextSetTempoEvent) || (lastTickOfBarToBeAdded > songDurationInTicks)) { var timeSignature = new TimeSignature { Numerator = currentTimeSignature.Numerator, Denominator = currentTimeSignature.Denominator }; var bar = new Bar { BarNumber = barNumber++, TicksFromBeginningOfSong = currentTick, TimeSignature = timeSignature, TempoInMicrosecondsPerQuarterNote = currentTempo }; bar.HasTriplets = HasBarTriplets(songSimplification, bar); retObj.Add(bar); currentTick += currentTimeSignature.Numerator * ticksPerBeat; lastTickOfBarToBeAdded += currentTimeSignature.Numerator * ticksPerBeat; if (currentTick >= songDurationInTicks) { break; } } if (lastTickOfBarToBeAdded >= timeOfNextTimeSignatureEvent) { timeSigIndex++; } if (lastTickOfBarToBeAdded >= timeOfNextSetTempoEvent) { tempoIndex++; } } return(retObj); }
protected bool Equals(TimeSignatureEvent other) { return(base.Equals(other) && Numerator == other.Numerator && Denominator == other.Denominator); }
static int Main(string[] args) { if (args.Length == 0) { Console.WriteLine("No midi file specified"); return(-1); } string midiFilePath = args[0]; if (!File.Exists(midiFilePath)) { Console.WriteLine("Cannot find midi file {0}", midiFilePath); return(-1); } string outputFile = midiFilePath + ".spi"; MidiFile midi = new MidiFile(midiFilePath); bool showMetaEvents = true; bool showUnknownEvents = false; bool showCalculations = false; int ticksPerQuarterNote = midi.DeltaTicksPerQuarterNote; double microsecondsPerQuarterNote = 500000f; using (var writer = new StreamWriter(outputFile, append: false)) { writer.WriteLine("# Sonic Pi source code generated from {0}", Path.GetFileName(midiFilePath)); if (showCalculations) { writer.WriteLine("# Tracks: {0}", midi.Tracks); for (int track = 0; track < midi.Tracks; ++track) { writer.WriteLine("# \tTrack {0} contains {1} events", track, midi.Events[track].Count()); } } writer.WriteLine(); // always process first track... for (int track = 0; track < midi.Tracks; ++track) { writer.WriteLine(); writer.WriteLine("# Track {0} ", track); foreach (MidiEvent @event in midi.Events[track]) { switch (@event.CommandCode) { case MidiCommandCode.NoteOn: { NoteOnEvent noteOn = @event as NoteOnEvent; if (noteOn != null) { // accumulate notes played at the same time? writer.WriteLine("play :{1} # {0}", noteOn.NoteNumber, noteOn.NoteName.Replace("#", "s")); if (noteOn.DeltaTime > 0) { writer.WriteLine("sleep {0}", DeltaTimeInSeconds(microsecondsPerQuarterNote, ticksPerQuarterNote, noteOn.DeltaTime)); } } } break; case MidiCommandCode.MetaEvent: if (showMetaEvents) { MetaEvent meta = @event as MetaEvent; if (meta != null) { switch (meta.MetaEventType) { case MetaEventType.TimeSignature: { TimeSignatureEvent tse = meta as TimeSignatureEvent; writer.WriteLine("# {0}", tse.ToString()); } break; case MetaEventType.SequenceTrackName: { TextEvent te = meta as TextEvent; writer.WriteLine("# Track Name: {0}", te.Text); } break; case MetaEventType.SetTempo: { TempoEvent te = meta as TempoEvent; microsecondsPerQuarterNote = te.MicrosecondsPerQuarterNote; writer.WriteLine("use_bpm {0}", Math.Floor(te.Tempo)); } break; } } } break; default: if (showUnknownEvents) { writer.WriteLine("# unknown command {0}", @event.ToString()); } break; } } } } return(0); }