public MidiTrack(byte[] instPrograms, byte[] drumPrograms, byte[] activeChannels, MidiEvent[] midiEvents) { Instruments = instPrograms; DrumInstruments = drumPrograms; ActiveChannels = activeChannels; MidiEvents = midiEvents; NoteOnCount = 0; EndTime = 0; }
public void CombineTracks() { var finalTrack = MergeTracks(); var absEvents = new MidiEvent[Tracks.Length][]; for (int i = 0; i < Tracks.Length; i++) { absEvents[i] = new MidiEvent[Tracks[i].MidiEvents.Length]; var totalDeltaTime = 0; for (int j = 0; j < Tracks[i].MidiEvents.Length; j++) { absEvents[i][j] = Tracks[i].MidiEvents[j]; totalDeltaTime += absEvents[i][j].DeltaTime; absEvents[i][j].DeltaTime = totalDeltaTime; } } var eventCount = 0; var delta = 0; var nextdelta = int.MaxValue; var counters = new int[absEvents.Length]; TypeUtils.ClearIntArray(counters); while (eventCount < finalTrack.MidiEvents.Length) { for (int x = 0; x < absEvents.Length; x++) { while (counters[x] < absEvents[x].Length && absEvents[x][counters[x]].DeltaTime == delta) { finalTrack.MidiEvents[eventCount] = absEvents[x][counters[x]]; eventCount++; counters[x]++; } if (counters[x] < absEvents[x].Length && absEvents[x][counters[x]].DeltaTime < nextdelta) nextdelta = absEvents[x][counters[x]].DeltaTime; } delta = nextdelta; nextdelta = int.MaxValue; } finalTrack.EndTime = finalTrack.MidiEvents[finalTrack.MidiEvents.Length - 1].DeltaTime; var deltaDiff = 0; for (int x = 0; x < finalTrack.MidiEvents.Length; x++) { var oldTime = finalTrack.MidiEvents[x].DeltaTime; finalTrack.MidiEvents[x].DeltaTime -= deltaDiff; deltaDiff = oldTime; } Tracks = new MidiTrack[] { finalTrack }; TrackFormat = MidiTrackFormat.SingleTrack; }
private void FireMidiMessageProcessed(MidiEvent e) { for (int i = 0; i < _midiMessageProcessed.Count; i++) { var l = _midiMessageProcessed[i]; if (l != null) { l(e); } } }
public void ProcessMidiMessage(MidiEvent e) { var command = e.Command; var channel = e.Channel; var data1 = e.Data1; var data2 = e.Data2; switch (command) { case MidiEventTypeEnum.NoteOff: NoteOff(channel, data1); break; case MidiEventTypeEnum.NoteOn: if (data2 == 0) NoteOff(channel, data1); else NoteOn(channel, data1, data2); break; case MidiEventTypeEnum.NoteAftertouch: //synth uses channel after touch instead break; case MidiEventTypeEnum.Controller: switch ((ControllerTypeEnum)data1) { case ControllerTypeEnum.BankSelectCoarse: //Bank select coarse if (channel == MidiHelper.DrumChannel) data2 += PatchBank.DrumBank; if (SoundBank.IsBankLoaded(data2)) _synthChannels[channel].BankSelect = (byte)data2; else _synthChannels[channel].BankSelect = (byte) ((channel == MidiHelper.DrumChannel) ? PatchBank.DrumBank : 0); break; case ControllerTypeEnum.ModulationCoarse: //Modulation wheel coarse _synthChannels[channel].ModRange.Coarse = (byte)data2; _synthChannels[channel].UpdateCurrentMod(); break; case ControllerTypeEnum.ModulationFine: //Modulation wheel fine _synthChannels[channel].ModRange.Fine = (byte)data2; _synthChannels[channel].UpdateCurrentMod(); break; case ControllerTypeEnum.VolumeCoarse: //Channel volume coarse _synthChannels[channel].Volume.Coarse = (byte)data2; break; case ControllerTypeEnum.VolumeFine: //Channel volume fine _synthChannels[channel].Volume.Fine = (byte)data2; break; case ControllerTypeEnum.PanCoarse: //Pan coarse _synthChannels[channel].Pan.Coarse = (byte)data2; _synthChannels[channel].UpdateCurrentPan(); break; case ControllerTypeEnum.PanFine: //Pan fine _synthChannels[channel].Pan.Fine = (byte)data2; _synthChannels[channel].UpdateCurrentPan(); break; case ControllerTypeEnum.ExpressionControllerCoarse: //Expression coarse _synthChannels[channel].Expression.Coarse = (byte)data2; _synthChannels[channel].UpdateCurrentVolume(); break; case ControllerTypeEnum.ExpressionControllerFine: //Expression fine _synthChannels[channel].Expression.Fine = (byte)data2; _synthChannels[channel].UpdateCurrentVolume(); break; case ControllerTypeEnum.HoldPedal: //Hold pedal if (_synthChannels[channel].HoldPedal && !(data2 > 63)) //if hold pedal is released stop any voices with pending release tags ReleaseHoldPedal(channel); _synthChannels[channel].HoldPedal = data2 > 63; break; case ControllerTypeEnum.LegatoPedal: //Legato Pedal _synthChannels[channel].LegatoPedal = data2 > 63; break; case ControllerTypeEnum.NonRegisteredParameterCourse: //NRPN Coarse Select //fix for invalid DataEntry after unsupported NRPN events _synthChannels[channel].Rpn.Combined = 0x3FFF; //todo implement NRPN break; case ControllerTypeEnum.NonRegisteredParameterFine: //NRPN Fine Select //fix for invalid DataEntry after unsupported NRPN events _synthChannels[channel].Rpn.Combined = 0x3FFF; //todo implement NRPN break; case ControllerTypeEnum.RegisteredParameterCourse: //RPN Coarse Select _synthChannels[channel].Rpn.Coarse = (byte)data2; break; case ControllerTypeEnum.RegisteredParameterFine: //RPN Fine Select _synthChannels[channel].Rpn.Fine = (byte)data2; break; case ControllerTypeEnum.AllNotesOff: //Note Off All NoteOffAll(false); break; case ControllerTypeEnum.DataEntryCoarse: //DataEntry Coarse switch (_synthChannels[channel].Rpn.Combined) { case 0: //change semitone, pitchwheel _synthChannels[channel].PitchBendRangeCoarse = (byte)data2; _synthChannels[channel].UpdateCurrentPitch(); break; case 1: //master fine tune coarse _synthChannels[channel].MasterFineTune.Coarse = (byte)data2; break; case 2: //master coarse tune coarse _synthChannels[channel].MasterCoarseTune = (short)(data2 - 64); break; } break; case ControllerTypeEnum.DataEntryFine: //DataEntry Fine switch (_synthChannels[channel].Rpn.Combined) { case 0: //change cents, pitchwheel _synthChannels[channel].PitchBendRangeFine = (byte)data2; _synthChannels[channel].UpdateCurrentPitch(); break; case 1: //master fine tune fine _synthChannels[channel].MasterFineTune.Fine = (byte)data2; break; } break; case ControllerTypeEnum.ResetControllers: //Reset All _synthChannels[channel].Expression.Combined = 0x3FFF; _synthChannels[channel].ModRange.Combined = 0; if (_synthChannels[channel].HoldPedal) ReleaseHoldPedal(channel); _synthChannels[channel].HoldPedal = false; _synthChannels[channel].LegatoPedal = false; _synthChannels[channel].Rpn.Combined = 0x3FFF; _synthChannels[channel].PitchBend.Combined = 0x2000; _synthChannels[channel].ChannelAfterTouch = 0; _synthChannels[channel].UpdateCurrentPitch(); //because pitchBend was reset _synthChannels[channel].UpdateCurrentVolume(); //because expression was reset break; default: return; } break; case MidiEventTypeEnum.ProgramChange: //Program Change _synthChannels[channel].Program = (byte)data1; break; case MidiEventTypeEnum.ChannelAftertouch: //Channel Aftertouch _synthChannels[channel].ChannelAfterTouch = (byte)data2; break; case MidiEventTypeEnum.PitchBend: //Pitch Bend _synthChannels[channel].PitchBend.Coarse = (byte)data2; _synthChannels[channel].PitchBend.Fine = (byte)data1; _synthChannels[channel].UpdateCurrentPitch(); break; } FireMidiMessageProcessed(e); }
public SynthEvent(MidiEvent e) { Event = e; }
private void MidiEventProcessed(MidiEvent midiEvent) { if (IsTempoMessage(midiEvent.Command, midiEvent.Data1)) { var meta = (MetaNumberEvent)midiEvent; CurrentTempo = (int)(MidiHelper.MicroSecondsPerMinute / meta.Value); } }
private static int TrackVoiceStats(MidiEvent midiEvent, FastList<byte> instList, FastList<byte> drumList, FastList<byte> channelList, int noteOnCount) { if (midiEvent.Command == MidiEventTypeEnum.NoteOn) { var chan = midiEvent.Channel; if (channelList.IndexOf((byte)chan) == -1) channelList.Add((byte)chan); noteOnCount++; } else if (midiEvent.Command == MidiEventTypeEnum.ProgramChange) { var chan = midiEvent.Channel; var prog = midiEvent.Data1; if (chan == MidiHelper.DrumChannel) { if (drumList.IndexOf((byte)prog) == -1) drumList.Add((byte)prog); } else { if (instList.IndexOf((byte)prog) == -1) instList.Add((byte)prog); } } return noteOnCount; }