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 FillWorkingBuffer() { lock (this) { /*Break the process loop into sections representing the smallest timeframe before the midi controls need to be updated * the bigger the timeframe the more efficent the process is, but playback quality will be reduced.*/ var sampleIndex = 0; var anySolo = _isAnySolo; for (int x = 0; x < MicroBufferCount; x++) { if (_midiEventQueue.Length > 0) { for (int i = 0; i < _midiEventCounts[x]; i++) { var m = _midiEventQueue.RemoveLast(); if (m.IsMetronome) { NoteOff(_metronomeChannel, 37); NoteOn(_metronomeChannel, 37, 95); } else { ProcessMidiMessage(m.Event); } } } //voice processing loop var node = _voiceManager.ActiveVoices.First; //node used to traverse the active voices while (node != null) { var channel = node.Value.VoiceParams.Channel; // channel is muted if it is either explicitley muted, or another channel is set to solo but not this one. var isChannelMuted = _mutedChannels.ContainsKey(channel) || (anySolo && !_soloChannels.ContainsKey(channel)); node.Value.Process(sampleIndex, sampleIndex + MicroBufferSize * SynthConstants.AudioChannels, isChannelMuted); //if an active voice has stopped remove it from the list if (node.Value.VoiceParams.State == VoiceStateEnum.Stopped) { var delnode = node; //node used to remove inactive voices node = node.Next; _voiceManager.RemoveVoiceFromRegistry(delnode.Value); _voiceManager.ActiveVoices.Remove(delnode); _voiceManager.FreeVoices.AddFirst(delnode.Value); } else { node = node.Next; } } sampleIndex += MicroBufferSize * SynthConstants.AudioChannels; } TypeUtils.ClearIntArray(_midiEventCounts); } }
private void FillWorkingBuffer() { /*Break the process loop into sections representing the smallest timeframe before the midi controls need to be updated * the bigger the timeframe the more efficent the process is, but playback quality will be reduced.*/ var sampleIndex = 0; for (int x = 0; x < MicroBufferCount; x++) { if (MidiEventQueue.Length > 0) { for (int i = 0; i < MidiEventCounts[x]; i++) { var m = MidiEventQueue.RemoveLast(); ProcessMidiMessage(m.Event); } } //voice processing loop var node = _voiceManager.ActiveVoices.First; //node used to traverse the active voices while (node != null) { node.Value.Process(sampleIndex, sampleIndex + MicroBufferSize * AudioChannels); //if an active voice has stopped remove it from the list if (node.Value.VoiceParams.State == VoiceStateEnum.Stopped) { var delnode = node; //node used to remove inactive voices node = node.Next; _voiceManager.RemoveVoiceFromRegistry(delnode.Value); _voiceManager.ActiveVoices.Remove(delnode); _voiceManager.FreeVoices.AddFirst(delnode.Value); } else { node = node.Next; } } sampleIndex += MicroBufferSize * AudioChannels; } TypeUtils.ClearIntArray(MidiEventCounts); }