示例#1
0
        private void HandleMidiNotesChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            IMidiNote[] itemsToRemove;
            IMidiNote[] itemsToAdd;

            lock (_voiceLock)
            {
                if (e.Action == NotifyCollectionChangedAction.Reset)
                {
                    // itemsToRemove is everything that used to be in the list but is not in the list now
                    itemsToRemove =
                        _lastNoteList.Where(on => !FindMatchingVoices(on).Any()).ToArray();
                    // itemsToAdd is evertying that is in the list now that wasn't the list before
                    itemsToAdd = _midiSource.ActiveNotes.Where(on => !_lastNoteList.Any(an => an.Number == on.Number)).ToArray();
                }
                else
                {
                    itemsToRemove = (e.OldItems ?? new IMidiNote[0]).OfType <IMidiNote>().ToArray();
                    itemsToAdd    = (e.NewItems ?? new IMidiNote[0]).OfType <IMidiNote>().ToArray();
                }

                foreach (int i in Enumerable.Range(0, itemsToRemove.Length))
                {
                    IMidiNote note = itemsToRemove[i];
                    IEnumerable <SimpleVoice> toKill = FindMatchingVoices(note);
                    toKill.Execute(KillNote);
                }

                foreach (IMidiNote note in itemsToAdd)
                {
                    SimpleVoice voice = GetLowestPriorityVoice();
                    // this could only be null if there are zero voices, which is not allowed
                    if (voice == null)
                    {
                        throw new InvalidOperationException("No voices found.");
                    }

                    voice.FromMidiNote = note;

                    if (NumberOfVoices > 1 || !IsLegato)
                    {
                        voice.Intensity = 0;
                    }

                    SetPitch(voice);

                    if (!voice.IsActive || NumberOfVoices > 1 || !IsLegato)
                    {
                        voice.Intensity = note.Velocity;
                    }

                    voice.IsActive = true;
                }

                _lastNoteList = _midiSource.ActiveNotes;
            }
        }
示例#2
0
 private void SetPitch(SimpleVoice voice)
 {
     if (voice.FromMidiNote != null)
     {
         // TODO this search could be optimized
         IScaleNote scaleNote = _scale.FirstOrDefault(n => n.MidiNoteNumber == voice.FromMidiNote.Number);
         if (scaleNote != null)
         {
             voice.Pitch = scaleNote.Pitch + (Pitch.HalfStep * PitchBendRange * _midiSource.PitchBend);
         }
     }
 }
示例#3
0
        public Guid?InjectNote(float pitch, float intensity)
        {
            SimpleVoice voice = GetLowestPriorityVoice();

            voice.IsActive     = false;
            voice.FromMidiNote = null;
            voice.Pitch        = pitch;
            voice.Intensity    = intensity;
            voice.Id           = Guid.NewGuid();

            return(voice.Id);
        }
示例#4
0
 private void RemoveVoices()
 {
     lock (_voiceLock)
     {
         while (_voices.Count > _numberOfVoices)
         {
             SimpleVoice voice = GetLowestPriorityVoice();
             if (voice != null)
             {
                 voice.IsActive = false;
                 _voices.Remove(voice);
             }
         }
     }
 }
示例#5
0
 private void KillNote(SimpleVoice voice)
 {
     voice.FromMidiNote.PropertyChanged -= HandleMidiNotePropertyChanged;
     voice.IsActive = false;
 }
示例#6
0
        private SimpleVoice GetLowestPriorityVoice()
        {
            SimpleVoice lowestPriority = _voices.OrderBy(v => !v.IsActive).ThenBy(v => v.StartTime).FirstOrDefault();

            return(lowestPriority);
        }